﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Diagnostics;
using System.Reflection;
using LTKJ.DataBase;
//using System.Threading;
using System.Globalization;
using System.Threading;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Windows.Forms.DataVisualization.Charting;
using System.Drawing;
using System.Runtime.InteropServices;
using WebSocketSharp.Server;
using System.Threading.Tasks;


namespace LTKJ.RTU
{
    public partial class FrmMain : Form
    {
        #region 公共变量

        //获取App.config配置参数
        public string strConnection = System.Configuration.ConfigurationManager.ConnectionStrings["OracleConnection"].ToString();

        //设置TCP委托
        public delegate void invokeDelegate();

        //树形结构变量     
        private DataTable dtTranPointTree = new DataTable(); //区域树数据     

        DataTable dtDevice = null;

        private Dictionary<string, Session> sessionPool = new Dictionary<string, Session>();
        List<string> cmdList = new List<string>();     //一般交接点指令
        List<string> rtuCmdList = new List<string>();     //一般交接点指令
        List<string> cmdWenList = new List<string>();  //稳定站指令
        string cylCmd = "";  //楚一联指令
        string cylWaterContentCmd = "";  //楚一联含水指令
        string hylCmd = "";//河一联指令

        private System.Windows.Forms.Timer timer1, timer2, timer3, timer4, monitorTimer;
        Socket Socket = null;
        private static Dictionary<string, TcpClient> Dic_tcp = new Dictionary<string, TcpClient>();
        private static Dictionary<string, TimeModel> Dic_time = new Dictionary<string, TimeModel>();
        int n = 0;
        WebSocketServer wssv = new WebSocketServer(9009);
        
        // 性能优化组件
        private DataCacheManager cacheManager;
        private AsyncTaskManager taskManager;
        
        // 线程管理和关闭控制
        private CancellationTokenSource cancellationTokenSource;
        private volatile bool isShuttingDown = false;
        #endregion

        /// <summary>
        /// 窗体初始化
        /// </summary>
        public FrmMain()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 窗体加载事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FrmMain_Load(object sender, EventArgs e)
        {
            try
            {
                icnSys.Text = Text;
                tsbtnClose.Click += TsbtnClose_Click;
                FormClosing += FrmMain_FormClosing;
                SizeChanged += FrmMain_SizeChanged;
                tsbtnExit.Click += TsbtnExit_Click;
                icnSys.Click += IcnSys_Click;

                // 初始化取消令牌
                cancellationTokenSource = new CancellationTokenSource();
                
                // 初始化性能优化组件
                InitializePerformanceComponents();

                Test();
                LoadData();
                InitCmd();
                InitSocket();

                timer2 = new System.Windows.Forms.Timer();
                timer2.Interval = 1000 * 10;
                timer2.Tick += timeSocketInit;
                timer2.Start();

                timer3 = new System.Windows.Forms.Timer();
                timer3.Interval = 1000 * 5;
                timer3.Tick += dataLost;
                timer3.Start();

                timer4 = new System.Windows.Forms.Timer();
                timer4.Interval = 1000 * 5;
                timer4.Tick += sysControl;
                timer4.Start();

                StartAllThreads();
                StartMonitor();
            }
            catch (Exception ex)
            {
                ShowMessageInWindow(MethodBase.GetCurrentMethod().Name + "\r\n" + ex.Message);
                Common.WriteErrorLog(MethodBase.GetCurrentMethod().Name + "\r\n" + ex.Message);//将出错信息写入错误日志           
            }
        }

        /// <summary>
        /// 初始化性能优化组件
        /// </summary>
        private void InitializePerformanceComponents()
        {
            try
            {
                // 初始化缓存管理器
                cacheManager = new DataCacheManager();
                cacheManager.OnCacheFlush += (message) => ShowMessageInWindow($"缓存: {message}");
                cacheManager.OnCacheError += (message) => ShowMessageInWindow($"缓存错误: {message}");
                
                // 连接数据插入事件
                cacheManager.OnDataInsertRequested += (deviceData) =>
                {
                    try
                    {
                        // 根据设备数据类型选择插入方法
                        if (deviceData.Flow1 > 0 || deviceData.Flow2 > 0)
                        {
                            // 流量数据
                            AddFlowRunData(deviceData, false); // false表示不显示消息
                        }
                        else
                        {
                            // 普通数据
                            AddRunData(deviceData, false);
                        }
                    }
                    catch (Exception ex)
                    {
                        ShowMessageInWindow($"缓存数据插入异常: {ex.Message}");
                        Common.WriteErrorLog($"缓存数据插入异常: {ex.Message}");
                    }
                };
                
                // 初始化异步任务管理器
                taskManager = new AsyncTaskManager();
                taskManager.OnTaskCompleted += (message) => ShowMessageInWindow($"任务: {message}");
                taskManager.OnTaskError += (message) => ShowMessageInWindow($"任务错误: {message}");
                taskManager.OnTaskTimeout += (message) => ShowMessageInWindow($"任务超时: {message}");
                
                // 初始化消息更新定时器
                messageUpdateTimer = new System.Windows.Forms.Timer();
                messageUpdateTimer.Interval = 100; // 100ms更新一次
                messageUpdateTimer.Tick += MessageUpdateTimer_Tick;
                messageUpdateTimer.Start();
                
                ShowMessageInWindow("性能优化组件初始化完成");
            }
            catch (Exception ex)
            {
                ShowMessageInWindow($"性能优化组件初始化失败: {ex.Message}");
                Common.WriteErrorLog($"性能优化组件初始化失败: {ex.Message}");
            }
        }

        public void wsWaterCollect()
        {
            while (!cancellationTokenSource?.Token.IsCancellationRequested == true && !isShuttingDown)
            {
                string ip = "192.169.40.21";
                int port = 502;
                string deviceName = "王四联";
                string deviceId = "2";
                TcpClient tcpClient = null;
                NetworkStream ntwStream = null;
                try
                {
                    // 检查取消令牌
                    if (cancellationTokenSource?.Token.IsCancellationRequested == true) break;
                    
                    //连接超时判断
                    tcpClient = new TcpClient();
                    tcpClient.Connect(IPAddress.Parse(ip), port);

                    ntwStream = tcpClient.GetStream();
                    // 设置读取超时时间为3秒
                    ntwStream.ReadTimeout = 3000;
                    // 设置写入超时时间为3秒
                    ntwStream.WriteTimeout = 3000;

                    if (ntwStream != null && ntwStream.CanWrite && ntwStream.CanRead)
                    {
                        ShowMessageInWindow("开始抄表：设备=【" + deviceName + "】 IP端口=" + ip + ":" + port);

                        try
                        {
                            //设备参数信息
                            ModelDevice mod = new ModelDevice();
                            mod.DeviceId = deviceId;
                            mod.DeviceName = deviceName;

                            // 设备编码1：读取含水数据（寄存器地址592，读2位）
                            string cmd1 = "";
                            string prex1 = "00 01 00 00 00 06 01 03 ";
                            cmd1 = prex1 + DEC_to_HEX(592) + " " + DEC_to_HEX(2);

                            // 设备编码2：读取含水数据（寄存器地址592，读2位）
                            string cmd2 = "";
                            string prex2 = "00 02 00 00 00 06 02 03 ";
                            cmd2 = prex2 + DEC_to_HEX(592) + " " + DEC_to_HEX(2);

                            string msg1 = SendCmd(ntwStream, cmd1);
                            msg1 = msg1.Replace(" ", "");
                            string msg2 = SendCmd(ntwStream, cmd2);
                            msg2 = msg2.Replace(" ", "");

                            // 解析设备编码1的含水数据
                            if (msg1.Length >= 18)
                            {
                                string s1 = msg1.Substring(18, 8); // 取8位十六进制数据（4个寄存器）
                                double water1 = StringToFloat2(s1);
                                mod.waterContent1 = water1;
                            }

                            // 解析设备编码2的含水数据
                            if (msg2.Length >= 18)
                            {
                                string s2 = msg2.Substring(18, 8); // 取8位十六进制数据（4个寄存器）
                                double water2 = StringToFloat2(s2);
                                mod.waterContent2 = water2;
                            }

                            // 使用缓存机制，避免频繁数据库操作
                            if (cacheManager != null)
                            {
                                cacheManager.CacheDeviceData(deviceId, mod);
                            }
                            else
                            {
                                // 降级到原有逻辑
                                if (Dic_time.ContainsKey(mod.DeviceId))
                                {
                                    DateTime tempTime = Dic_time[mod.DeviceId].commonTime;
                                    TimeSpan tspan = new TimeSpan();
                                    tspan = DateTime.Now - tempTime;
                                    if (tspan.TotalMinutes > 1)
                                    {
                                        string stime = DateTime.Now.ToString("yyyy-MM-dd HH:mm");
                                        string message = "{ \"flag\":\"1\",\"tranPointId\":\"" + mod.DeviceId + "\",\"stime\":\"" + stime + "\",\"water1\":\"" + mod.waterContent1 + "\",\"water2\":\"" + mod.waterContent2 + "\"}";
                                        webSocketSendMessage("/Chat", message);
                                        Dic_time[mod.DeviceId].commonTime = DateTime.Now;
                                    }
                                }
                                else
                                {
                                    TimeModel timeModel = new TimeModel();
                                    timeModel.commonTime = DateTime.Now;
                                    timeModel.flowTime = DateTime.Now;
                                    Dic_time.Add(mod.DeviceId, timeModel);
                                }
                                AddWsWaterData(mod, true);
                            }

                            // 异步发送WebSocket消息
                            if (taskManager != null)
                            {
                                taskManager.QueueTask(async () =>
                                {
                                    try
                                    {
                                        string stime = DateTime.Now.ToString("yyyy-MM-dd HH:mm");
                                        string message = "{ \"flag\":\"1\",\"tranPointId\":\"" + mod.DeviceId + "\",\"stime\":\"" + stime + "\",\"water1\":\"" + mod.waterContent1 + "\",\"water2\":\"" + mod.waterContent2 + "\"}";
                                        webSocketSendMessage("/Chat", message);
                                    }
                                    catch (Exception ex)
                                    {
                                        Common.WriteErrorLog($"WebSocket消息发送异常: {ex.Message}");
                                    }
                                }, "WebSocket消息发送");
                            }
                        }
                        catch (Exception ex)
                        {
                            ShowMessageInWindow(ex.Message);
                            Common.WriteErrorLog("数据处理异常" + "\r\n" + ex.Message);//将出错信息写入错误日志           
                        }
                    }
                    else
                    {
                        ShowMessageInWindow("抄表失败：设备=【" + deviceName + "】");
                        if (ntwStream != null)
                        {
                            ntwStream.Close();
                        }
                        tcpClient.Close();
                        SafeClose(tcpClient.Client);
                    }
                    if (ntwStream != null)
                    {
                        ntwStream.Close();
                    }
                    if (tcpClient != null)
                    {
                        tcpClient.Close();
                        SafeClose(tcpClient.Client);
                        tcpClient = null;
                    }

                }
                catch (OperationCanceledException)
                {
                    // 正常取消，退出循环
                    break;
                }
                catch (Exception ex)
                {
                    ShowMessageInWindow(MethodBase.GetCurrentMethod().Name + "\r\n" + ex.Message);
                    Common.WriteErrorLog(MethodBase.GetCurrentMethod().Name + "\r\n" + ex.Message);//将出错信息写入错误日志           
                    if (ntwStream != null)
                    {
                        ntwStream.Close();
                    }
                    if (tcpClient != null)
                    {
                        tcpClient.Close();
                        SafeClose(tcpClient.Client);
                        tcpClient = null;
                    }
                }

                // 使用Task.Delay替代Delay方法，避免阻塞
                if (cancellationTokenSource?.Token.IsCancellationRequested == true) break;
                Task.Delay(10 * 1000, cancellationTokenSource?.Token ?? CancellationToken.None).Wait();
            }
        }

        public void cylCollect()
        {
            while (!cancellationTokenSource?.Token.IsCancellationRequested == true && !isShuttingDown)
            {
                string ip = "192.168.98.107";
                int port = 502;
                string deviceName = "楚一联";
                string deviceId = "4";
                TcpClient tcpClient = null;
                NetworkStream ntwStream = null;
                try
                {
                    //连接超时判断
                    tcpClient = new TcpClient();
                    tcpClient.Connect(IPAddress.Parse(ip), port);

                    ntwStream = tcpClient.GetStream();
                    // 设置读取超时时间为10秒
                    ntwStream.ReadTimeout = 3000;
                    // 设置写入超时时间为10秒
                    ntwStream.WriteTimeout = 3000;

                    if (ntwStream != null && ntwStream.CanWrite && ntwStream.CanRead)
                    {
                        ShowMessageInWindow("开始抄表：设备=【" + deviceName + "】 IP端口=" + ip + ":" + port);

                        try
                        {
                            //设备参数信息
                            ModelDevice mod = new ModelDevice();
                            mod.DeviceId = deviceId;
                            string cmd1 = "07 04 00 00 00 04 F1 AF";
                            string cmd2 = "08 04 00 00 00 04 F1 50";
                            string msg1 = SendCmd(ntwStream, cmd1);
                            msg1 = msg1.Replace(" ", "");
                            string msg2 = SendCmd(ntwStream, cmd2);
                            msg2 = msg2.Replace(" ", "");
                            if (msg1.Length == 26 && msg2.Length == 26)
                            {
                                mod.DeviceId = deviceId;
                                mod.DeviceName = deviceName;
                                string s1 = msg1.Substring(6, 16);
                                string s2 = msg2.Substring(6, 16);
                                mod.Flow1 = Convert.ToInt32(s1.Substring(0, 8), 16) / 10d;
                                mod.Flow2 = Convert.ToInt32(s2.Substring(0, 8), 16) / 10d;
                                mod.Flow1Rate = StringToFloat(s1.Substring(8, 8));
                                mod.Flow2Rate = StringToFloat(s2.Substring(8, 8));

                                if (Dic_time.ContainsKey(mod.DeviceId))
                                {
                                    DateTime tempTime = Dic_time[mod.DeviceId].flowTime;
                                    TimeSpan tspan = new TimeSpan();
                                    tspan = DateTime.Now - tempTime;
                                    if (tspan.TotalMinutes > 1)
                                    {
                                        string stime = DateTime.Now.ToString("yyyy-MM-dd HH:mm");
                                        string message = "{ \"flag\":\"2\",\"tranPointId\":\"" + mod.DeviceId + "\",\"stime\":\"" + stime + "\",\"flow1\":\"" + mod.Flow1 + "\",\"flow2\":\"" + mod.Flow2 + "\",\"flow1Rate\":\"" + mod.Flow1Rate + "\",\"flow2Rate\":\"" + mod.Flow2Rate + "\"}";
                                        webSocketSendMessage("/Chat", message);
                                        Dic_time[mod.DeviceId].flowTime = DateTime.Now;
                                    }
                                }
                                else
                                {
                                    TimeModel timeModel = new TimeModel();
                                    timeModel.commonTime = DateTime.Now;
                                    timeModel.flowTime = DateTime.Now;
                                    Dic_time.Add(mod.DeviceId, timeModel);
                                }
                                AddFlowRunData(mod, true);
                            }


                        }
                        catch (Exception ex)
                        {
                            ShowMessageInWindow(ex.Message);
                            Common.WriteErrorLog("数据处理异常" + "\r\n" + ex.Message);//将出错信息写入错误日志           
                        }
                    }
                    else
                    {
                        ShowMessageInWindow("抄表失败：设备=【" + deviceName + "】");
                        if (ntwStream != null)
                        {
                            ntwStream.Close();
                        }
                        tcpClient.Close();
                        SafeClose(tcpClient.Client);
                    }
                    if (ntwStream != null)
                    {
                        ntwStream.Close();
                    }
                    if (tcpClient != null)
                    {
                        tcpClient.Close();
                        SafeClose(tcpClient.Client);
                        tcpClient = null;
                    }

                }
                catch (Exception ex)
                {
                    ShowMessageInWindow(MethodBase.GetCurrentMethod().Name + "\r\n" + ex.Message);
                    Common.WriteErrorLog(MethodBase.GetCurrentMethod().Name + "\r\n" + ex.Message);//将出错信息写入错误日志           
                    if (ntwStream != null)
                    {
                        ntwStream.Close();
                    }
                    if (tcpClient != null)
                    {
                        tcpClient.Close();
                        SafeClose(tcpClient.Client);
                        tcpClient = null;
                    }
                }
                Delay(10 * 1000);
            }
        }

        public void hylCollect()
        {
         
        }

        public void InitWebSockt()
        {
            wssv.AddWebSocketService<Chat>("/Chat");
            wssv.Start();
            if (wssv.IsListening)
            {
                ShowMessageInWindow("Listening on port " + wssv.Port + ", and providing WebSocket services:");
                foreach (var path in wssv.WebSocketServices.Paths)
                    ShowMessageInWindow("- " + path);
            }
            while (!cancellationTokenSource?.Token.IsCancellationRequested == true && !isShuttingDown)
            {
                if (!wssv.IsListening)
                {
                    break;
                }
                
                try
                {
                    // 使用Task.Delay替代无限循环，避免CPU占用过高
                    Task.Delay(1000, cancellationTokenSource?.Token ?? CancellationToken.None).Wait();
                }
                catch (OperationCanceledException)
                {
                    break; // 取消操作，退出循环
                }
            }
            ShowMessageInWindow("webSocket服务断开");
            wssv.Stop();
        }

        /// <summary>
        /// websocket发送消息
        /// </summary>
        /// <param name="channnel">频道</param>
        /// <param name="message">消息</param>
        public void webSocketSendMessage(string channel, string message)
        {
            channel = channel.Trim();
            if (channel.IndexOf('/') == -1)
            {
                channel = "/" + channel;
            }
            foreach (WebSocketServiceHost host in wssv.WebSocketServices.Hosts)
            {

                if (channel.Equals(host.Path))
                {
                    wssv.WebSocketServices.Broadcast(message);
                }
            }
        }

        public void timeSocketInit(object sender, EventArgs e)
        {
            InitSocket();

            n++;
            if (n >= 10)
            {
                n = 0;
                ClearMemory();
                ConnectSockets();
            }

        }

        public void sysControl(object sender, EventArgs e)
        {
            try
            {
                DataTable dt = Common.GetTableData("SYS_CONTROL", "and mark=0", "", "id", "asc");
                for (int i = 0; i < dt.Rows.Count; i++)
                {
                    string opId = "";
                    string tranPointId = "";
                    string tranPointName = "";
                    try
                    {
                        opId = dt.Rows[i]["id"].ToString();
                        tranPointId = dt.Rows[i]["Tran_point_id"].ToString();
                        tranPointName = dt.Rows[i]["Tran_point_name"].ToString();
                        string flowNum = dt.Rows[i]["flow_num"].ToString();
                        string ip = dt.Rows[i]["ip"].ToString();
                        string cmdValue = dt.Rows[i]["cmd_value"].ToString();
                        string stimeStr = dt.Rows[i]["stime"].ToString();
                        DateTime stime = Convert.ToDateTime(stimeStr);
                        double value = double.Parse(cmdValue);
                        value = value * 10;  //设置的值需要乘以10
                        value = Math.Round(value, 0);
                        cmdValue = value.ToString();
                        TimeSpan tSpan = DateTime.Now - stime;
                        if (tSpan.TotalMinutes > 8)
                        {
                            Common.ExecuteNonQuery("update sys_control set status='失败',remark='指令超时，超时3分钟',mark=1 where id='" + opId + "'");
                            continue;
                        }
                        TcpClient tcpClient = new TcpClient();
                        NetworkStream ntwStream = null;
                        int port = 502;
                        try
                        {
                            //连接超时判断
                            IAsyncResult ar = tcpClient.BeginConnect(IPAddress.Parse(ip), port, null, null);
                            bool isConnect = ar.AsyncWaitHandle.WaitOne(3000);
                            if (!isConnect) { throw new Exception("连接超时，无法连接到指定设备"); }

                            ntwStream = tcpClient.GetStream();
                            // 设置读取超时时间为10秒
                            ntwStream.ReadTimeout = 3000;
                            // 设置写入超时时间为10秒
                            ntwStream.WriteTimeout = 3000;
                        }
                        catch (Exception ex)
                        {
                            ShowMessageInWindow(tranPointName + " 建立tcpclient失败: " + ex.Message);
                            Common.WriteErrorLog(tranPointName + " 建立tcpclient失败: " + MethodBase.GetCurrentMethod().Name + "\r\n" + ex.Message + "\r\n");
                            continue;
                        }

                        if (ntwStream.CanWrite && ntwStream.CanRead)
                        {
                            if ("1".Equals(flowNum))
                            {
                                //00 01 00 00 00 09 01 10 00 00 00 01 02 00 0F 
                                flowBaseDataModel mod = getFlowBase(cmdValue);
                                string cmd = "0001 0000 000B 01 10 " + DEC_to_HEX(3094) + " " + DEC_to_HEX(2) + " 02 " + DEC_to_HEX(mod.low) + " " + DEC_to_HEX(mod.high);
                                string result = SendCmd(ntwStream, cmd);
                                cmd = cmd.Replace(" ", "");
                                result = result.Replace(" ", "");
                                if (result.Length == 24 && result.Substring(12, 12) == cmd.Substring(12, 12))
                                {
                                    ShowMessageInWindow(tranPointName + "修改底数成功");
                                }
                                else
                                {
                                    Common.ExecuteNonQuery("update sys_control set status='失败',remark='修改底数失败',mark=1 where id='" + opId + "'");
                                    continue;
                                }

                                cmd = "0001 0000 0006 01 05 " + DEC_to_HEX(3559) + " FF 00";
                                result = SendCmd(ntwStream, cmd);
                                cmd = cmd.Replace(" ", "");
                                result = result.Replace(" ", "");
                                if (result.Equals(cmd))
                                {
                                    ShowMessageInWindow(tranPointName + "重置脉冲数成功");
                                }
                                else
                                {
                                    Common.ExecuteNonQuery("update sys_control set status='失败',remark='重置脉冲数失败',mark=1 where id='" + opId + "'");
                                    continue;
                                }

                                Common.ExecuteNonQuery("update sys_control set status='成功',mark=1 where id='" + opId + "'");


                            }
                            if ("2".Equals(flowNum))
                            {
                                //00 01 00 00 00 09 01 10 00 00 00 01 02 00 0F 
                                flowBaseDataModel mod = getFlowBase(cmdValue);
                                string cmd = "0001 0000 000B 01 10 " + DEC_to_HEX(3090) + " " + DEC_to_HEX(2) + " 02 " + DEC_to_HEX(mod.low) + " " + DEC_to_HEX(mod.high);
                                string result = SendCmd(ntwStream, cmd);
                                cmd = cmd.Replace(" ", "");
                                result = result.Replace(" ", "");
                                if (result.Length == 24 && result.Substring(12, 12) == cmd.Substring(12, 12))
                                {
                                    ShowMessageInWindow(tranPointName + "修改底数成功");
                                }
                                else
                                {
                                    Common.ExecuteNonQuery("update sys_control set status='失败',remark='修改底数失败',mark=1 where id='" + opId + "'");
                                    continue;
                                }

                                cmd = "0001 0000 0006 01 06 " + DEC_to_HEX(3039) + " 00 01";
                                result = SendCmd(ntwStream, cmd);
                                cmd = cmd.Replace(" ", "");
                                result = result.Replace(" ", "");
                                if (result.Equals(cmd))
                                {
                                    ShowMessageInWindow(tranPointName + "重置脉冲数成功");
                                }
                                else
                                {
                                    Common.ExecuteNonQuery("update sys_control set status='失败',remark='重置脉冲数失败',mark=1 where id='" + opId + "'");
                                    continue;
                                }

                                Common.ExecuteNonQuery("update sys_control set status='成功',mark=1 where id='" + opId + "'");

                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        ShowMessageInWindow("执行控制指令出现异常" + ex.Message);
                    }
                }
            }
            catch (Exception ex)
            {
                ShowMessageInWindow("执行控制指令出现异常" + ex.Message);
            }

        }

        private string SendCmd(NetworkStream ntwStream, string cmdData)
        {
            string strData = string.Empty;
            try
            {
                if (ntwStream.CanWrite)
                {
                    byte[] bytSend = Common.HexStringToByteArray(cmdData);   //16进制字符串指令转换为字节数组发送
                    ntwStream.Write(bytSend, 0, bytSend.Length);

                    //获取接收数据
                    byte[] data = new byte[2048];
                    int bytes = ntwStream.Read(data, 0, data.Length);
                    strData = Common.ByteArrayToHexString(data, 0, bytes);  //接收字节数组转换为16进制字符串指令
                }
                else
                {
                    ShowMessageInWindow("无法写入数据流");
                    strData = "";
                }
            }
            catch (Exception ex)
            {
                strData = "";
                ShowMessageInWindow(ex.Message);
            }
            return strData;
        }

        public void dataLost(object sender, EventArgs e)
        {
            try
            {
                DataTable dt = Common.GetTableData("data_lost_info", "and mark=0", "", "id", "asc");
                for (int i = 0; i < dt.Rows.Count; i++)
                {
                    string opId = "";
                    string tranPointId = "";
                    string tranPointName = "";
                    try
                    {
                        opId = dt.Rows[i]["CMD_SEQ"].ToString();
                        tranPointId = dt.Rows[i]["Tran_point_id"].ToString();
                        tranPointName = dt.Rows[i]["Tran_point_name"].ToString();
                        string ip = dt.Rows[i]["ip"].ToString();
                        string startTimeStr = dt.Rows[i]["start_time"].ToString();
                        string endTimeStr = dt.Rows[i]["end_time"].ToString();
                        DateTime startTime = Convert.ToDateTime(startTimeStr);
                        DateTime endTime = Convert.ToDateTime(endTimeStr);
                        TimeSpan tspan = new TimeSpan();
                        tspan = endTime - startTime;
                        if (tspan.TotalMinutes < 1)
                        {
                            Common.ExecuteNonQuery("update data_lost_info set mark=2,remark='已经完成断点续传' where mark=0 and cmd_seq='" + opId + "'");
                            continue;
                        }

                        tspan = DateTime.Now - endTime;
                        if (tspan.TotalDays >= 7)
                        {
                            Common.ExecuteNonQuery("update data_lost_info set mark=1,remark='超出了7天' where mark=0 and cmd_seq='" + opId + "'");
                            continue;
                        }
                        tspan = DateTime.Now - startTime;
                        if (tspan.TotalDays >= 7)
                        {
                            DateTime temp = DateTime.Now.AddDays(-7);
                            string tDay = string.Format("{0:d}", temp);
                            startTime = Convert.ToDateTime(tDay + " 00:00:00");
                        }
                        string tempDay1 = string.Format("{0:d}", DateTime.Now);
                        DateTime t1 = Convert.ToDateTime(tempDay1 + " 00:00:00");
                        string tempDay2 = string.Format("{0:d}", startTime);
                        DateTime t2 = Convert.ToDateTime(tempDay2 + " 00:00:00");
                        tspan = t1 - t2;
                        long days = tspan.Days;
                        tspan = startTime - t2;
                        double minutes = tspan.TotalMinutes;
                        minutes = Math.Round(minutes, 0);
                        string cmd = "";
                        if ("5".Equals(tranPointId))   //稳定站
                        {
                            cmd = DEC_to_HEX(opId) + "0000 000a 0114 0706 " + DEC_to_HEX(days.ToString()) + DEC_to_HEX(minutes.ToString()) + "0026";
                        }
                        else
                        {
                            cmd = DEC_to_HEX(opId) + "0000 000a 0114 0706 " + DEC_to_HEX(days.ToString()) + DEC_to_HEX(minutes.ToString()) + "0020";
                        }
                        Session session = sessionPool[ip];
                        if (session.SockeClient == null)
                        {
                            continue;
                        }
                        byte[] data = Common.HexStringToByteArray(cmd);
                        Send(session.SockeClient, data);
                    }
                    catch (Exception ex)
                    {
                        ShowMessageInWindow("断点续传出现异常 " + ex.Message);
                    }
                }
            }
            catch (Exception ex)
            {
                ShowMessageInWindow("断点续传出现异常 " + ex.Message);
            }
        }

        public void InitSocket()
        {
            try
            {
              
                dtDevice = Common.GetTableData("tran_Point", "and ip is not null ", "", "id", "asc");
                for (int i = 0; i < dtDevice.Rows.Count; i++)
                {
                    string ip = dtDevice.Rows[i]["ip"].ToString();
                    if (sessionPool.ContainsKey(ip))
                    {
                        if (!sessionPool[ip].SockeClient.Connected)
                        {
                            AsynConnect(ip, 502);
                        }
                    }
                    else
                    {
                        AsynConnect(ip, 502);
                    }
                }
                List<string> ips = new List<string>();
                ips.Add("192.168.98.107");  //楚一联
               // ips.Add("192.168.98.147");  //楚一联 含水
                ips.Add("192.169.60.77");  //楚一联 含水
                                            //    ips.Add("192.168.110.253"); // 河一联
                for (int i = 0; i < ips.Count; i++)
                {
                    string ip = ips[i];
                    if (sessionPool.ContainsKey(ip))
                    {
                        if (!sessionPool[ip].SockeClient.Connected)
                        {
                            AsynConnect(ip, 502);
                        }
                    }
                    else
                    {
                        AsynConnect(ip, 502);
                    }
                }
            }
            catch (Exception ex)
            {
                ShowMessageInWindow(ex.Message);
            }

        }

        public void ConnectSockets()
        {
            try
            {
                dtDevice = Common.GetTableData("tran_Point", "and ip is not null", "", "id", "asc");
                for (int i = 0; i < dtDevice.Rows.Count; i++)
                {
                    string ip = dtDevice.Rows[i]["ip"].ToString();
                    AsynConnect(ip, 502);
                }
                List<string> ips = new List<string>();
                ips.Add("192.168.98.107");  //楚一联
                //ips.Add("192.168.110.253"); // 河一联
                for (int i = 0; i < ips.Count; i++)
                {
                    string ip = ips[i];
                    if (sessionPool.ContainsKey(ip))
                    {
                        Session session=  sessionPool[ip];                   
                        SafeClose(session.SockeClient);
                    }
                    AsynConnect(ip, 502);
                }
            }
            catch (Exception ex)
            {
                ShowMessageInWindow(ex.Message);
            }

        }

        public void LoadData()
        {
            dtDevice = Common.GetTableData("tran_Point", "", "", "id", "asc");
            //左侧树形结构
            for (int i = 0; i < dtDevice.Rows.Count; i++)
            {
                TreeNode treeNode = new TreeNode();
                treeNode.Tag = dtDevice.Rows[i]["ID"].ToString();
                treeNode.Text = dtDevice.Rows[i]["NAME"].ToString();
                tvTranPointTree.Nodes.Add(treeNode);

            }
        }

        /// <summary>
        /// 连接到服务器
        /// </summary>
        public void AsynConnect(string IP, int Port)
        {
            try
            {
                //端口及IP
                IPEndPoint ipe = new IPEndPoint(IPAddress.Parse(IP), Port);
                //创建套接字
                Socket socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                Session session = new Session();
                session.SockeClient = socketClient;
                session.IP = IP;
                byte[] buffer = new byte[4096];
                session.buffer = buffer;

                //开始连接到服务器
                socketClient.BeginConnect(ipe, new AsyncCallback(ConnectCallBack), session);
                if (sessionPool.ContainsKey(IP))
                {
                    sessionPool.Remove(IP);
                    sessionPool.Add(IP, session);
                }
                else
                {
                    sessionPool.Add(session.IP, session);
                }

            }
            catch (Exception ex)
            {
                ShowMessageInWindow("AsynConnect 连接服务器异常 " + ex.Message);
            }

        }

        private void ConnectCallBack(IAsyncResult iar)
        {
            Session session = (Session)iar.AsyncState;
            if (session == null) return;
            Socket client = session.SockeClient;
            if (client == null) return;
            try
            {
                client.EndConnect(iar);
                ShowMessageInWindow("ConnectCallBack 已连接服务器");
                //接收客户端的数据
                //  AsynRecive(client);
                //实现异步接受消息的方法 客户端不断监听消息
                client.BeginReceive(session.buffer, 0, session.buffer.Length, SocketFlags.None, new AsyncCallback(AsynRecive), session);
            }
            catch (SocketException e)
            {
                if (e.ErrorCode == 10061)
                {
                    ShowMessageInWindow("ConnectCallBack 服务器程序未运行或服务器端口未开放");
                }
                else
                {
                    ShowMessageInWindow("ConnectCallBack  " + e.Message);
                }
            }
            catch (Exception ex)
            {
                ShowMessageInWindow("ConnectCallBack  " + ex.Message);
            }

        }


        #region 处理接收的数据
        /// <summary>
        /// 处理接受的数据
        /// </summary>
        /// <param name="socket"></param>
        public void AsynRecive(IAsyncResult iar)
        {
            Session session = iar.AsyncState as Session;
            if (session == null) return;
            string ip = session.IP;
            Socket SockeClient = session.SockeClient;
            try
            {
                if (SockeClient == null || !SockeClient.Connected)
                {
                    return;
                }
                int length = SockeClient.EndReceive(iar);
                if (length == 0)
                {
                    return;
                }
                string msg = Common.ByteArrayToHexString(session.buffer, 0, length);
                ShowMessageInWindow("返回数据 " + msg);
                msg = msg.Replace(" ", "");
                int msgLength = msg.Length;
                string cmdSeq = "";
                int seq = 0;
                if (msg.Length >= 4)
                {
                    cmdSeq = msg.Substring(0, 4);
                    seq = Convert.ToInt32(cmdSeq, 16);
                }
                if (cmdSeq == "0001" && msgLength == 66)
                {

                    ModelDevice mod = new ModelDevice();
                    DataRow[] rows = dtDevice.Select("ip='" + ip + "'");
                    string id = "";
                    string name = "";
                    if (rows.Count() == 1)
                    {
                        id = rows[0]["id"].ToString();
                        name = rows[0]["name"].ToString();
                    }
                    else
                    {
                        return;
                    }

                    mod.DeviceId = id;
                    mod.DeviceName = name;
                    string s = msg.Substring(18, 48);
                    mod.Temperature1 = Convert.ToInt32(s.Substring(0, 4), 16) / (double)100;
                    mod.Temperature2 = Convert.ToInt32(s.Substring(8, 4), 16) / (double)100;
                    mod.Pressure1 = Convert.ToInt32(s.Substring(16, 4), 16) / (double)100;
                    mod.Pressure2 = Convert.ToInt32(s.Substring(24, 4), 16) / (double)100;
                    mod.waterContent1 = Convert.ToInt32(s.Substring(32, 4), 16) / (double)100;
                    mod.waterContent2 = Convert.ToInt32(s.Substring(40, 4), 16) / (double)100;
                    //宁一联流程1的压力温度含水和流程2一样
                    if (mod.DeviceId == "1")
                    {
                        mod.Temperature2 = mod.Temperature1;
                        mod.Pressure2 = mod.Pressure1;
                        mod.waterContent2 = mod.waterContent1;
                    }
                    if (Dic_time.ContainsKey(mod.DeviceId))
                    {
                        DateTime tempTime = Dic_time[mod.DeviceId].commonTime;
                        TimeSpan tspan = new TimeSpan();
                        tspan = DateTime.Now - tempTime;
                        if (tspan.TotalMinutes > 1)
                        {
                            string stime = DateTime.Now.ToString("yyyy-MM-dd HH:mm");
                            string message = "{ \"flag\":\"1\",\"tranPointId\":\"" + mod.DeviceId + "\",\"stime\":\"" + stime + "\",\"temp1\":\"" + mod.Temperature1 + "\",\"temp2\":\"" + mod.Temperature2 + "\",\"press1\":\"" + mod.Pressure1 + "\",\"press2\":\"" + mod.Pressure2 + "\",\"water1\":\"" + mod.waterContent1 + "\",\"water2\":\"" + mod.waterContent2 + "\"}";
                            webSocketSendMessage("/Chat", message);
                            Dic_time[mod.DeviceId].commonTime = DateTime.Now;
                        }
                    }
                    else
                    {
                        TimeModel timeModel = new TimeModel();
                        timeModel.commonTime = DateTime.Now;
                        timeModel.flowTime = DateTime.Now;
                        Dic_time.Add(mod.DeviceId, timeModel);
                    }
                    AddRunData(mod, true);
                }

                if (cmdSeq == "0002" && msgLength == 82)
                {
                    ModelDevice mod = new ModelDevice();
                    DataRow[] rows = dtDevice.Select("ip='" + ip + "'");
                    string id = "";
                    string name = "";
                    if (rows.Count() == 1)
                    {
                        id = rows[0]["id"].ToString();
                        name = rows[0]["name"].ToString();
                    }
                    else
                    {
                        return;
                    }

                    mod.DeviceId = id;
                    mod.DeviceName = name;
                    string s = msg.Substring(18, 64);
                    string flow1Str = s.Substring(4, 4) + s.Substring(0, 4);
                    mod.Flow1 = Convert.ToInt32(flow1Str, 16) / (double)10;
                    string flow2Str = s.Substring(20, 4) + s.Substring(16, 4);
                    mod.Flow2 = Convert.ToInt32(flow2Str, 16) / (double)10;
                    mod.Flow1Rate = Convert.ToInt32(s.Substring(32, 4), 16) / 10d;
                    mod.Flow1Rate = mod.Flow1Rate * 60d;
                    mod.Flow2Rate = Convert.ToInt32(s.Substring(48, 4), 16) / 10d;
                    mod.Flow2Rate = mod.Flow2Rate * 60d;


                    //宁一 瞬时和累计地址互调
                    if ("1".Equals(mod.DeviceId) || "3".Equals(mod.DeviceId))
                    {
                        mod.Flow1 = Convert.ToInt32(s.Substring(36, 4) + s.Substring(32, 4), 16) / (double)100;
                        mod.Flow2 = Convert.ToInt32(s.Substring(52, 4) + s.Substring(48, 4), 16) / (double)100;
                        mod.Flow1Rate = Convert.ToInt32(s.Substring(4, 4) + s.Substring(0, 4), 16) / 100d;
                        mod.Flow2Rate = Convert.ToInt32(s.Substring(20, 4) + s.Substring(16, 4), 16) / 100d;
                        //ShowMessageInWindowTest(s);
                        //ShowMessageInWindowTest(mod.Flow1 + " " + mod.Flow2 + " " + mod.Flow1Rate + " " + mod.Flow2Rate);
                    }
                    //王四联 流量计除以10
                    if ("2".Equals(mod.DeviceId) || "7".Equals(mod.DeviceId) || "8".Equals(mod.DeviceId))
                    {
                        mod.Flow1 = Convert.ToInt32(s.Substring(36, 4) + s.Substring(32, 4), 16) / (double)10;
                        mod.Flow2 = Convert.ToInt32(s.Substring(52, 4) + s.Substring(48, 4), 16) / (double)10;
                        mod.Flow1Rate = Convert.ToInt32(s.Substring(4, 4) + s.Substring(0, 4), 16) / 100d;
                        mod.Flow2Rate = Convert.ToInt32(s.Substring(20, 4) + s.Substring(16, 4), 16) / 100d;
                        //ShowMessageInWindowTest(s);
                        //ShowMessageInWindowTest(mod.Flow1 + " " + mod.Flow2 + " " + mod.Flow1Rate + " " + mod.Flow2Rate);
                    }

                    if (Dic_time.ContainsKey(mod.DeviceId))
                    {
                        DateTime tempTime = Dic_time[mod.DeviceId].flowTime;
                        TimeSpan tspan = new TimeSpan();
                        tspan = DateTime.Now - tempTime;
                        if (tspan.TotalMinutes > 1)
                        {
                            string stime = DateTime.Now.ToString("yyyy-MM-dd HH:mm");
                            string message = "{ \"flag\":\"2\",\"tranPointId\":\"" + mod.DeviceId + "\",\"stime\":\"" + stime + "\",\"flow1\":\"" + mod.Flow1 + "\",\"flow2\":\"" + mod.Flow2 + "\",\"flow1Rate\":\"" + mod.Flow1Rate + "\",\"flow2Rate\":\"" + mod.Flow2Rate + "\"}";
                            webSocketSendMessage("/Chat", message);
                            Dic_time[mod.DeviceId].flowTime = DateTime.Now;
                        }
                    }
                    else
                    {
                        TimeModel timeModel = new TimeModel();
                        timeModel.commonTime = DateTime.Now;
                        timeModel.flowTime = DateTime.Now;
                        Dic_time.Add(mod.DeviceId, timeModel);
                    }

                    AddFlowRunData(mod, true);
                }
                if (cmdSeq == "0003" && msgLength == 182)
                {
                    //里一联的数据
                    ModelDevice mod = new ModelDevice();
                    mod.DeviceId = "5";
                    mod.DeviceName = "里一联";
                    string data = msg.Substring(18, 164);
                    string s = data.Substring(0, 48);
                    mod.Temperature1 = Convert.ToInt32(s.Substring(0, 4), 16) / (double)100;
                    mod.Temperature2 = Convert.ToInt32(s.Substring(8, 4), 16) / (double)100;
                    mod.Pressure1 = Convert.ToInt32(s.Substring(16, 4), 16) / (double)100;
                    mod.Pressure2 = Convert.ToInt32(s.Substring(24, 4), 16) / (double)100;
                    mod.waterContent1 = Convert.ToInt32(s.Substring(32, 4), 16) / (double)100;
                    mod.waterContent2 = Convert.ToInt32(s.Substring(40, 4), 16) / (double)100;
                    if (Dic_time.ContainsKey(mod.DeviceId))
                    {
                        DateTime tempTime = Dic_time[mod.DeviceId].commonTime;
                        TimeSpan tspan = new TimeSpan();
                        tspan = DateTime.Now - tempTime;
                        if (tspan.TotalMinutes > 1)
                        {
                            string stime = DateTime.Now.ToString("yyyy-MM-dd HH:mm");
                            string message = "{ \"flag\":\"1\",\"tranPointId\":\"" + mod.DeviceId + "\",\"stime\":\"" + stime + "\",\"temp1\":\"" + mod.Temperature1 + "\",\"temp2\":\"" + mod.Temperature2 + "\",\"press1\":\"" + mod.Pressure1 + "\",\"press2\":\"" + mod.Pressure2 + "\",\"water1\":\"" + mod.waterContent1 + "\",\"water2\":\"" + mod.waterContent2 + "\"}";
                            webSocketSendMessage("/Chat", message);
                            Dic_time[mod.DeviceId].commonTime = DateTime.Now;
                        }
                    }
                    else
                    {
                        TimeModel timeModel = new TimeModel();
                        timeModel.commonTime = DateTime.Now;
                        timeModel.flowTime = DateTime.Now;
                        Dic_time.Add(mod.DeviceId, timeModel);
                    }
                    AddRunData(mod, true);

                    s = data.Substring(100, 64);
                    string flow1Str = s.Substring(4, 4) + s.Substring(0, 4);
                    mod.Flow1 = Convert.ToInt32(flow1Str, 16) / (double)10;
                    string flow2Str = s.Substring(20, 4) + s.Substring(16, 4);
                    mod.Flow2 = Convert.ToInt32(flow2Str, 16) / (double)10;
                    mod.Flow1Rate = Convert.ToInt32(s.Substring(32, 4), 16) / 10d;
                    mod.Flow1Rate = mod.Flow1Rate * 60d;
                    mod.Flow2Rate = Convert.ToInt32(s.Substring(48, 4), 16) / 10d;
                    mod.Flow2Rate = mod.Flow2Rate * 60d;

                    //里一联 
                    if ("5".Equals(mod.DeviceId))
                    {
                        mod.Flow1 = Convert.ToInt32(s.Substring(36, 4) + s.Substring(32, 4), 16) / (double)100;
                        mod.Flow2 = Convert.ToInt32(s.Substring(52, 4) + s.Substring(48, 4), 16) / (double)100;
                        mod.Flow1Rate = Convert.ToInt32(s.Substring(4, 4) + s.Substring(0, 4), 16) / 100d;
                        mod.Flow2Rate = Convert.ToInt32(s.Substring(20, 4) + s.Substring(16, 4), 16) / 100d;
                        //ShowMessageInWindowTest(s);
                        //ShowMessageInWindowTest(mod.Flow1+" "+mod.Flow2+" "+mod.Flow1Rate+" "+mod.Flow2Rate);
                    }

                    AddFlowRunData(mod, true);
                    if (Dic_time.ContainsKey(mod.DeviceId))
                    {
                        DateTime tempTime = Dic_time[mod.DeviceId].flowTime;
                        TimeSpan tspan = new TimeSpan();
                        tspan = DateTime.Now - tempTime;
                        if (tspan.TotalMinutes > 1)
                        {
                            string stime = DateTime.Now.ToString("yyyy-MM-dd HH:mm");
                            string message = "{ \"flag\":\"2\",\"tranPointId\":\"" + mod.DeviceId + "\",\"stime\":\"" + stime + "\",\"flow1\":\"" + mod.Flow1 + "\",\"flow2\":\"" + mod.Flow2 + "\",\"flow1Rate\":\"" + mod.Flow1Rate + "\",\"flow2Rate\":\"" + mod.Flow2Rate + "\"}";
                            webSocketSendMessage("/Chat", message);
                            Dic_time[mod.DeviceId].flowTime = DateTime.Now;
                        }
                    }
                    else
                    {
                        TimeModel timeModel = new TimeModel();
                        timeModel.commonTime = DateTime.Now;
                        timeModel.flowTime = DateTime.Now;
                        Dic_time.Add(mod.DeviceId, timeModel);
                    }

                    //处理河一联
                    ModelDevice mod1 = new ModelDevice();
                    mod1.DeviceId = "6";
                    mod1.DeviceName = "河一联";
                    s = data.Substring(48, 48);
                    mod1.Temperature1 = Convert.ToInt32(s.Substring(0, 4), 16) / (double)100;
                    mod1.Temperature2 = Convert.ToInt32(s.Substring(8, 4), 16) / (double)100;
                    mod1.Pressure1 = Convert.ToInt32(s.Substring(16, 4), 16) / (double)100;
                    mod1.Pressure2 = Convert.ToInt32(s.Substring(24, 4), 16) / (double)100;
                    mod1.waterContent1 = Convert.ToInt32(s.Substring(32, 4), 16) / (double)100;
                    mod1.waterContent2 = Convert.ToInt32(s.Substring(40, 4), 16) / (double)100;

                    if (Dic_time.ContainsKey(mod1.DeviceId))
                    {
                        DateTime tempTime = Dic_time[mod1.DeviceId].commonTime;
                        TimeSpan tspan = new TimeSpan();
                        tspan = DateTime.Now - tempTime;
                        if (tspan.TotalMinutes > 1)
                        {
                            string stime = DateTime.Now.ToString("yyyy-MM-dd HH:mm");
                            string message = "{ \"flag\":\"1\",\"tranPointId\":\"" + mod1.DeviceId + "\",\"stime\":\"" + stime + "\",\"temp1\":\"" + mod1.Temperature1 + "\",\"temp2\":\"" + mod1.Temperature2 + "\",\"press1\":\"" + mod1.Pressure1 + "\",\"press2\":\"" + mod1.Pressure2 + "\",\"water1\":\"" + mod1.waterContent1 + "\",\"water2\":\"" + mod1.waterContent2 + "\"}";
                            webSocketSendMessage("/Chat", message);
                            Dic_time[mod1.DeviceId].commonTime = DateTime.Now;
                        }
                    }
                    else
                    {
                        TimeModel timeModel = new TimeModel();
                        timeModel.commonTime = DateTime.Now;
                        timeModel.flowTime = DateTime.Now;
                        Dic_time.Add(mod1.DeviceId, timeModel);
                    }

                    AddRunData(mod1, true);
                }
                //楚一联使用modbus rtu协议
                if (msg.Length == 66 && ("61031C".Equals(msg.Substring(0, 6))))
                {
                    ModelDevice mod = new ModelDevice();
                    string id = "4";
                    string name = "楚一联";

                    mod.DeviceId = id;
                    mod.DeviceName = name;
                    string s = msg.Substring(6, 56);
                    mod.Flow2 = StringToFloat2(s.Substring(0, 8));
                    mod.Flow2 = mod.Flow2 / 10d;
                    mod.Flow2Rate = StringToFloat2(s.Substring(40, 8)) / 10d;
                    AddCylFlow2Data(mod, true);
                }

                //楚一联使用modbus rtu协议
                if ("000E".Equals(cmdSeq))
                {
                  //Tx: 000 - 00 0E 00 00 00 06 01 03 02 50 00 02
                  //Rx: 001 - 00 0E 00 00 00 07 01 03 04 48 2E 3D CB

                    ModelDevice mod = new ModelDevice();
                    string id = "4";
                    string name = "楚一联";

                    mod.DeviceId = id;
                    mod.DeviceName = name;
                    string s = msg.Substring(18, 8);
                    double d = StringToFloat2(s);
                    mod.waterContent1 = d;
                    AddCylWaterContentData(mod, true);
                }

                //河一联 一路流量
                if (cmdSeq == "0004" && msgLength == 50)
                {
                    ModelDevice mod = new ModelDevice();
                    string id = "6";
                    string name = "河一联";

                    mod.DeviceId = id;
                    mod.DeviceName = name;
                    string s = msg.Substring(18, 32);
                    mod.Flow1 = Convert.ToInt32(s.Substring(4, 4) + s.Substring(0, 4), 16) / 10d;
                    mod.Flow2 = Convert.ToInt32(s.Substring(12, 4) + s.Substring(8, 4), 16) / 10d;
                    mod.Flow1Rate = Convert.ToInt32(s.Substring(20, 4) + s.Substring(16, 4), 16) / (double)100d;
                    mod.Flow2Rate = Convert.ToInt32(s.Substring(28, 4) + s.Substring(24, 4), 16) / (double)100d;
                    //临时调换流程
                    double temp = 0d;
                    temp = mod.Flow1;
                    mod.Flow1 = mod.Flow2;
                    mod.Flow2 = temp;

                    temp = mod.Flow1Rate;
                    mod.Flow1Rate = mod.Flow2Rate;
                    mod.Flow2Rate = temp;


                    if (Dic_time.ContainsKey(mod.DeviceId))
                    {
                        DateTime tempTime = Dic_time[mod.DeviceId].flowTime;
                        TimeSpan tspan = new TimeSpan();
                        tspan = DateTime.Now - tempTime;
                        if (tspan.TotalMinutes > 1)
                        {
                            string stime = DateTime.Now.ToString("yyyy-MM-dd HH:mm");
                            string message = "{ \"flag\":\"2\",\"tranPointId\":\"" + mod.DeviceId + "\",\"stime\":\"" + stime + "\",\"flow1\":\"" + mod.Flow1 + "\",\"flow2\":\"" + mod.Flow2 + "\",\"flow1Rate\":\"" + mod.Flow1Rate + "\",\"flow2Rate\":\"" + mod.Flow2Rate + "\"}";
                            webSocketSendMessage("/Chat", message);
                            Dic_time[mod.DeviceId].flowTime = DateTime.Now;
                        }
                    }
                    else
                    {
                        TimeModel timeModel = new TimeModel();
                        timeModel.commonTime = DateTime.Now;
                        timeModel.flowTime = DateTime.Now;
                        Dic_time.Add(mod.DeviceId, timeModel);
                    }

                    AddFlowRunData(mod, true);
                }
                if (seq > 1000)
                {
                    if (msgLength >= 154 && !("192.168.60.252").Equals(session.IP)) //普通站
                    {
                        string cmdFlag = msg.Substring(12, 4);
                        if (!"0114".Equals(cmdFlag))
                        {
                            return;
                        }
                        string timeStampStr = msg.Substring(26, 8);
                        long timeStamp = Convert.ToUInt32(timeStampStr, 16);
                        DateTime breakTime = GetDateTime(timeStamp);
                        ModelDevice mod = new ModelDevice();
                        DataRow[] rows = dtDevice.Select("ip='" + ip + "'");
                        string id = "";
                        string name = "";
                        if (rows.Count() == 1)
                        {
                            id = rows[0]["id"].ToString();
                            name = rows[0]["name"].ToString();
                        }
                        else
                        {
                            return;
                        }
                        mod.DeviceId = id;
                        mod.DeviceName = name;
                        mod.BreakTime = breakTime;
                        string data = msg.Substring(42, 80);

                        string s = data.Substring(0, 48);
                        mod.Temperature1 = Convert.ToInt32(s.Substring(4, 4), 16) / (double)100;
                        mod.Temperature2 = Convert.ToInt32(s.Substring(12, 4), 16) / (double)100;
                        mod.Pressure1 = Convert.ToInt32(s.Substring(20, 4), 16) / (double)100;
                        mod.Pressure2 = Convert.ToInt32(s.Substring(28, 4), 16) / (double)100;
                        mod.waterContent1 = Convert.ToInt32(s.Substring(36, 4), 16) / (double)100;
                        mod.waterContent2 = Convert.ToInt32(s.Substring(44, 4), 16) / (double)100;
                        //宁一联流程1的压力温度含水和流程2一样
                        if (mod.DeviceId == "1")
                        {
                            mod.Temperature2 = mod.Temperature1;
                            mod.Pressure2 = mod.Pressure1;
                            mod.waterContent2 = mod.waterContent1;
                        }

                        s = data.Substring(48, 32);
                        mod.Flow1 = Convert.ToInt32(s.Substring(0, 8), 16) / (double)10;
                        mod.Flow2 = Convert.ToInt32(s.Substring(8, 8), 16) / (double)10;
                        mod.Flow1Rate = Convert.ToInt32(s.Substring(20, 4), 16) / 10d;
                        mod.Flow1Rate = mod.Flow1Rate * 60d;
                        mod.Flow2Rate = Convert.ToInt32(s.Substring(28, 4), 16) / 10d;
                        mod.Flow2Rate = mod.Flow2Rate * 60d;
                        //宁一联换流程
                        if (mod.DeviceId == "1")
                        {
                            double temp = 0;
                            temp = mod.Flow1;
                            mod.Flow1 = mod.Flow2;
                            mod.Flow2 = temp;                     

                            temp = mod.Flow1Rate;
                            mod.Flow1Rate = mod.Flow2Rate;
                            mod.Flow2Rate = temp;
                        }

                      

                        if ( "3".Equals(mod.DeviceId))
                        {
                            mod.Flow1Rate = Convert.ToInt32(s.Substring(0, 8), 16) / (double)100;
                            mod.Flow2Rate = Convert.ToInt32(s.Substring(8, 8), 16) / (double)100;
                            mod.Flow1 = Convert.ToInt32(s.Substring(16, 8), 16) / 100d;
                            mod.Flow2 = Convert.ToInt32(s.Substring(24, 8), 16) / 100d;
                            //ShowMessageInWindowTest(s);
                            //ShowMessageInWindowTest(mod.Flow1 + " " + mod.Flow2 + " " + mod.Flow1Rate + " " + mod.Flow2Rate);
                        }

                        //王四联 流量计除以10
                        if ("1".Equals(mod.DeviceId) || "2".Equals(mod.DeviceId) || "7".Equals(mod.DeviceId) || "8".Equals(mod.DeviceId))
                        {
                            mod.Flow1Rate = Convert.ToInt32(s.Substring(0, 8), 16) / (double)100;
                            mod.Flow2Rate = Convert.ToInt32(s.Substring(8, 8), 16) / (double)100;
                            mod.Flow1 = Convert.ToInt32(s.Substring(16, 8), 16) / 10d;
                            mod.Flow2 = Convert.ToInt32(s.Substring(24, 8), 16) / 10d;
                            //ShowMessageInWindowTest(s);
                            //ShowMessageInWindowTest(mod.Flow1 + " " + mod.Flow2 + " " + mod.Flow1Rate + " " + mod.Flow2Rate);
                        }

                        AddLostData(mod, true);
                        Common.ExecuteNonQuery("update data_lost_info set start_time=start_time+1/(24*60) where mark=0 and cmd_seq='" + seq + "'");

                    }
                    if (msgLength >= 202 && ("192.169.22.25").Equals(session.IP)) //稳定站
                    {
                        string cmdFlag = msg.Substring(12, 4);
                        if (!"0114".Equals(cmdFlag))
                        {
                            return;
                        }
                        string timeStampStr = msg.Substring(26, 8);
                        long timeStamp = Convert.ToUInt32(timeStampStr, 16);
                        DateTime breakTime = GetDateTime(timeStamp);
                        ModelDevice mod = new ModelDevice();
                        mod.DeviceId = "5";
                        mod.DeviceName = "里一联";
                        mod.BreakTime = breakTime;
                        string data = msg.Substring(42, 80);

                        string s = data.Substring(0, 48);
                        mod.Temperature1 = Convert.ToInt32(s.Substring(4, 4), 16) / (double)100;
                        mod.Temperature2 = Convert.ToInt32(s.Substring(12, 4), 16) / (double)100;
                        mod.Pressure1 = Convert.ToInt32(s.Substring(20, 4), 16) / (double)100;
                        mod.Pressure2 = Convert.ToInt32(s.Substring(28, 4), 16) / (double)100;
                        mod.waterContent1 = Convert.ToInt32(s.Substring(36, 4), 16) / (double)100;
                        mod.waterContent2 = Convert.ToInt32(s.Substring(44, 4), 16) / (double)100;

                        s = data.Substring(48, 32);
                        mod.Flow1 = Convert.ToInt32(s.Substring(0, 8), 16) / (double)10;
                        mod.Flow2 = Convert.ToInt32(s.Substring(8, 8), 16) / (double)10;
                        mod.Flow1Rate = Convert.ToInt32(s.Substring(20, 4), 16) / 10d;
                        mod.Flow1Rate = mod.Flow1Rate * 60d;
                        mod.Flow2Rate = Convert.ToInt32(s.Substring(28, 4), 16) / 10d;
                        mod.Flow2Rate = mod.Flow2Rate * 60d;
                        if ("5".Equals(mod.DeviceId))
                        {
                            mod.Flow1Rate = Convert.ToInt32(s.Substring(0, 8), 16) / (double)100;
                            mod.Flow2Rate = Convert.ToInt32(s.Substring(8, 8), 16) / (double)100;
                            mod.Flow1 = Convert.ToInt32(s.Substring(16, 8), 16) / 100d;
                            mod.Flow2 = Convert.ToInt32(s.Substring(24, 8), 16) / 100d;
                            //ShowMessageInWindowTest(s);
                            //ShowMessageInWindowTest(mod.Flow1 + " " + mod.Flow2 + " " + mod.Flow1Rate + " " + mod.Flow2Rate);
                        }
                        AddLostData(mod, true);
                        Common.ExecuteNonQuery("update data_lost_info set start_time=start_time+1/(24*60) where mark=0 and cmd_seq='" + seq + "'");
                    }
                    if (msgLength == 18)
                    {
                        if (msg.Substring(12, 4) == "0194")
                        {
                            Common.ExecuteNonQuery("update data_lost_info set start_time=start_time+1/(24*60) where mark=0 and cmd_seq='" + seq + "'");
                        }
                    }
                }
                //rtu 协议 基础数据
                //Tx:  01 03 0B E9 00 0C 96 1F
                // Rx: 01 03 18 0C 7E 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 0B 00 00 00 00 00 00 2D 01

                if (msg.Length == 58 && "010318".Equals(msg.Substring(0, 6)))
                {
                    ModelDevice mod = new ModelDevice();
                    DataRow[] rows = dtDevice.Select("ip='" + ip + "'");
                    string id = "";
                    string name = "";
                    if (rows.Count() == 1)
                    {
                        id = rows[0]["id"].ToString();
                        name = rows[0]["name"].ToString();
                    }
                    else
                    {
                        return;
                    }

                    mod.DeviceId = id;
                    mod.DeviceName = name;
                    string s = msg.Substring(6, 48);
                    mod.Temperature1 = Convert.ToInt32(s.Substring(0, 4), 16) / (double)100;
                    mod.Temperature2 = Convert.ToInt32(s.Substring(8, 4), 16) / (double)100;
                    mod.Pressure1 = Convert.ToInt32(s.Substring(16, 4), 16) / (double)100;
                    mod.Pressure2 = Convert.ToInt32(s.Substring(24, 4), 16) / (double)100;
                    mod.waterContent1 = Convert.ToInt32(s.Substring(32, 4), 16) / (double)100;
                    mod.waterContent2 = Convert.ToInt32(s.Substring(40, 4), 16) / (double)100;
                    //宁一联流程1的压力温度含水和流程2一样
                    if (mod.DeviceId == "1")
                    {
                        mod.Temperature2 = mod.Temperature1;
                        mod.Pressure2 = mod.Pressure1;
                        mod.waterContent2 = mod.waterContent1;
                    }
                    if (Dic_time.ContainsKey(mod.DeviceId))
                    {
                        DateTime tempTime = Dic_time[mod.DeviceId].commonTime;
                        TimeSpan tspan = new TimeSpan();
                        tspan = DateTime.Now - tempTime;
                        if (tspan.TotalMinutes > 1)
                        {
                            string stime = DateTime.Now.ToString("yyyy-MM-dd HH:mm");
                            string message = "{ \"flag\":\"1\",\"tranPointId\":\"" + mod.DeviceId + "\",\"stime\":\"" + stime + "\",\"temp1\":\"" + mod.Temperature1 + "\",\"temp2\":\"" + mod.Temperature2 + "\",\"press1\":\"" + mod.Pressure1 + "\",\"press2\":\"" + mod.Pressure2 + "\",\"water1\":\"" + mod.waterContent1 + "\",\"water2\":\"" + mod.waterContent2 + "\"}";
                            webSocketSendMessage("/Chat", message);
                            Dic_time[mod.DeviceId].commonTime = DateTime.Now;
                        }
                    }
                    else
                    {
                        TimeModel timeModel = new TimeModel();
                        timeModel.commonTime = DateTime.Now;
                        timeModel.flowTime = DateTime.Now;
                        Dic_time.Add(mod.DeviceId, timeModel);
                    }
                    AddRunData(mod, true);
                }
                //Tx:01 03 0C 02 00 10 E6 96
                //Rx:01 03 20 9B 6C 00 00 00 00 00 00 04 0A 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 8B 45

                if (msg.Length == 74 && "010320".Equals(msg.Substring(0, 6)))
                {
                    ModelDevice mod = new ModelDevice();
                    DataRow[] rows = dtDevice.Select("ip='" + ip + "'");
                    string id = "";
                    string name = "";
                    if (rows.Count() == 1)
                    {
                        id = rows[0]["id"].ToString();
                        name = rows[0]["name"].ToString();
                    }
                    else
                    {
                        return;
                    }

                    mod.DeviceId = id;
                    mod.DeviceName = name;
                    string s = msg.Substring(6, 64);
                    string flow1Str = s.Substring(4, 4) + s.Substring(0, 4);
                    mod.Flow1 = Convert.ToInt32(flow1Str, 16) / (double)10;
                    string flow2Str = s.Substring(20, 4) + s.Substring(16, 4);
                    mod.Flow2 = Convert.ToInt32(flow2Str, 16) / (double)10;
                    mod.Flow1Rate = Convert.ToInt32(s.Substring(32, 4), 16) / 10d;
                    mod.Flow1Rate = mod.Flow1Rate * 60d;
                    mod.Flow2Rate = Convert.ToInt32(s.Substring(48, 4), 16) / 10d;
                    mod.Flow2Rate = mod.Flow2Rate * 60d;


                    //宁一联 只有一路线，换流程
                    if ("1".Equals(mod.DeviceId))
                    {
                        mod.Flow1 = Convert.ToInt32(flow2Str, 16) / (double)10;
                        mod.Flow2 = Convert.ToInt32(flow1Str, 16) / (double)10;
                        mod.Flow1Rate = Convert.ToInt32(s.Substring(48, 4), 16) / 10d;
                        mod.Flow1Rate = mod.Flow1Rate * 60d;
                        mod.Flow2Rate = Convert.ToInt32(s.Substring(32, 4), 16) / 10d;
                        mod.Flow2Rate = mod.Flow2Rate * 60d;
                    }

                    if (Dic_time.ContainsKey(mod.DeviceId))
                    {
                        DateTime tempTime = Dic_time[mod.DeviceId].flowTime;
                        TimeSpan tspan = new TimeSpan();
                        tspan = DateTime.Now - tempTime;
                        if (tspan.TotalMinutes > 1)
                        {
                            string stime = DateTime.Now.ToString("yyyy-MM-dd HH:mm");
                            string message = "{ \"flag\":\"2\",\"tranPointId\":\"" + mod.DeviceId + "\",\"stime\":\"" + stime + "\",\"flow1\":\"" + mod.Flow1 + "\",\"flow2\":\"" + mod.Flow2 + "\",\"flow1Rate\":\"" + mod.Flow1Rate + "\",\"flow2Rate\":\"" + mod.Flow2Rate + "\"}";
                            webSocketSendMessage("/Chat", message);
                            Dic_time[mod.DeviceId].flowTime = DateTime.Now;
                        }
                    }
                    else
                    {
                        TimeModel timeModel = new TimeModel();
                        timeModel.commonTime = DateTime.Now;
                        timeModel.flowTime = DateTime.Now;
                        Dic_time.Add(mod.DeviceId, timeModel);
                    }

                    AddFlowRunData(mod, true);
                }

                SockeClient.BeginReceive(session.buffer, 0, session.buffer.Length, SocketFlags.None, new AsyncCallback(AsynRecive), session);
            }
            catch (Exception ex)
            {
                //  SockeClient.Disconnect(true);
                ShowMessageInWindow(string.Format("客户端 {0}  异常  {1}", ip, ex.Message));
            }
        }

        /// <summary>  
        /// 时间戳Timestamp转换成日期  
        /// </summary>  
        /// <param name="timeStamp"></param>  
        /// <returns></returns>  
        private DateTime GetDateTime(long timeStamp)
        {
            DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
            long lTime = (timeStamp * 10000000);
            TimeSpan toNow = new TimeSpan(lTime);
            DateTime targetDt = dtStart.Add(toNow);
            return targetDt;
        }

        /// <summary>
        /// 发送消息
        /// </summary>
        /// <param name="s_socket">指定客户端socket</param>
        /// <param name="bytes">发送消息</param>
        public void Send(Socket c_socket, byte[] bytes)
        {
            try
            {
                //发送
                c_socket.BeginSend(bytes, 0, bytes.Length, SocketFlags.None, asyncResult =>
                {
                    try
                    {
                        //完成消息发送
                        int len = c_socket.EndSend(asyncResult);
                    }
                    catch (Exception ex)
                    {
                        if (c_socket != null)
                        {
                            c_socket.Close();
                            c_socket = null;
                        }
                        ShowMessageInWindow("error ex=" + ex.Message + " " + ex.StackTrace);
                    }
                }, null);

            }
            catch (Exception ex)
            {
                if (c_socket != null)
                {
                    c_socket.Close();
                    c_socket = null;
                }
            }
        }

        #endregion

        public void Test()
        {
            string msg = "00 02 00 00 00 23 01 03 20 4f cd 00 0b 00 00 00 00 1d 73 00 19 00 00 00 00 00 00 00 00 00 00 00 00 08 ec 00 00 00 00 00 00 ";
            msg = msg.Replace(" ", "");
            string cmdSeq = msg.Substring(0, 4);
            int msgLength = msg.Length;
            if (cmdSeq == "0002" && msgLength == 82)
            {
                ModelDevice mod = new ModelDevice();
                mod.DeviceId = "3";
                string s = msg.Substring(18, 64);
                string flow1Str = s.Substring(4, 4) + s.Substring(0, 4);
                mod.Flow1 = Convert.ToInt32(flow1Str, 16) / (double)10;
                string flow2Str = s.Substring(20, 4) + s.Substring(16, 4);
                mod.Flow2 = Convert.ToInt32(flow2Str, 16) / (double)10;
                mod.Flow1Rate = Convert.ToInt32(s.Substring(32, 4), 16) / 10d;
                mod.Flow1Rate = mod.Flow1Rate * 60d;
                mod.Flow2Rate = Convert.ToInt32(s.Substring(48, 4), 16) / 10d;
                mod.Flow2Rate = mod.Flow2Rate * 60d;

                //宁一联 只有一路线，换流程
                if ("1".Equals(mod.DeviceId))
                {
                    mod.Flow1 = Convert.ToInt32(flow2Str, 16) / (double)10;
                    mod.Flow2 = Convert.ToInt32(flow1Str, 16) / (double)10;
                    mod.Flow1Rate = Convert.ToInt32(s.Substring(48, 4), 16) / 10d;
                    mod.Flow1Rate = mod.Flow1Rate * 60d;
                    mod.Flow2Rate = Convert.ToInt32(s.Substring(32, 4), 16) / 10d;
                    mod.Flow2Rate = mod.Flow2Rate * 60d;
                }
            }
        }

        //00 03 00 00 00 0a 01 14 07 06 00 01 00 00 00 10
        public void InitCmd()
        {
            //一般站点采集指令 温度压力含水
            string cmd = "";
            string prex = "00 01 00 00 00 06 01 03 ";
            cmd = prex + DEC_to_HEX(3049) + " " + DEC_to_HEX(12);
            cmdList.Add(cmd);

            //一般站点采集指令 流量计读数
            prex = "00 02 00 00 00 06 01 03 ";
            cmd = prex + DEC_to_HEX(3074) + " " + DEC_to_HEX(16);
            cmdList.Add(cmd);

            //一般站点采集指令 温度压力含水  rtu协议

            cmd = "0103" + DEC_to_HEX(3049) + " " + DEC_to_HEX(12);
            cmd = Full_Crc(cmd);
            rtuCmdList.Add(cmd);

            //一般站点采集指令 流量计读数  rtu协议        
            cmd = "0103" + DEC_to_HEX(3074) + " " + DEC_to_HEX(16);
            cmd = Full_Crc(cmd);
            rtuCmdList.Add(cmd);

            //稳定站指令
            prex = "00 03 00 00 00 06 01 03 ";
            cmd = prex + DEC_to_HEX(3049) + " " + DEC_to_HEX(41);
            cmdWenList.Add(cmd);

            //楚一联采集指令 modbus rtu协议        
            cylCmd = "61 03 0B EA 00 0E EE 7E";
            cylWaterContentCmd = "00 0E 00 00 00 06 01 03 02 50 00 02";

            hylCmd = "00 04 00 00 00 06 01 03 0C 18 00 08";

        }

        /// <summary>
        /// Close the socket safely.
        /// </summary>
        /// <param name="socket">The socket.</param>
        public void SafeClose(Socket socket)
        {
            try
            {
                if (socket == null)
                    return;

                if (!socket.Connected)
                    return;
            }
            catch
            {

            }

            try
            {
                socket.Shutdown(SocketShutdown.Both);
                Delay(20);
                socket.Close();
            }
            catch
            {
            }
        }

        /// <summary>
        /// 关闭所有socket
        /// </summary>
        /// <param name="dic"></param>
        public void CloseAllSocket(Dictionary<string, Session> dic)
        {
            try
            {
                foreach (Session session in dic.Values)
                {
                    SafeClose(session.SockeClient);
                }
            }
            catch (Exception ex)
            {

            }

        }

        private void CollectData()
        {
            while (!cancellationTokenSource?.Token.IsCancellationRequested == true && !isShuttingDown)
            {
                try
                {
                    // 使用Task.Delay替代Delay方法，避免UI阻塞
                    Task.Delay(1000, cancellationTokenSource?.Token ?? CancellationToken.None).Wait();
                }
                catch (OperationCanceledException)
                {
                    break; // 取消操作，退出循环
                }

                //   CollectCy1Flow1();

                try
                {
                    List<string> keys = new List<string>(sessionPool.Keys);
                    if (sessionPool.Count() > 0)
                    {
                        for (int i = 0; i < cmdList.Count(); i++)
                        {
                            for (int j = sessionPool.Count - 1; j >= 0; j--)
                            {
                                if (keys.Count <= j)
                                {
                                    ShowMessageInWindow($"警告：keys索引越界，j={j}");
                                    continue;
                                }
                                Session session = sessionPool[keys[j]];
                                if (session == null)
                                {
                                    ShowMessageInWindow($"警告：session为null，IP={keys[j]}");
                                    continue;
                                }
                                if (session.SockeClient == null || !IsSocketConnected(session.SockeClient))
                                {
                                    ShowMessageInWindow($"Socket失效，自动重连: {session.IP}");
                                    SafeClose(session.SockeClient);
                                    sessionPool.Remove(session.IP);
                                    AsynConnect(session.IP, 502);
                                    continue;
                                }
                                if (session.SockeClient.Connected)
                                {
                                    string cmd = "";
                                    if ("192.169.22.25".Equals(session.IP))
                                    {
                                        cmd = cmdWenList[0];   //稳定站特殊，使用特殊指令
                                    }
                                    //else if ("192.168.98.107".Equals(session.IP))
                                    //{
                                    //    cmd = cylCmd;  //楚一联特殊，使用特殊指令
                                    //}
                                    else if ("192.169.60.77".Equals(session.IP))
                                    {
                                        cmd = cylWaterContentCmd;  //楚一联含水特殊，使用特殊指令
                                    }
                                    //else if ("192.168.60.252".Equals(session.IP))
                                    //{
                                    //    cmd = hylCmd;  //河一联特殊，使用特殊指令
                                    //}
                                    //else if ("192.168.88.41".Equals(session.IP))
                                    //{
                                    //    cmd = rtuCmdList[i];  //宁一联 modbus rtu协议
                                    //}
                                    else
                                    {
                                        cmd = cmdList[i];
                                    }
                                    byte[] data = Common.HexStringToByteArray(cmd);
                                    ShowMessageInWindow("发送指令： " + cmd);
                                    Send(session.SockeClient, data);

                                    if ("192.169.22.25".Equals(session.IP))
                                    {
                                        string cmd1 = hylCmd;   //稳定站特殊，使用特殊指令
                                        byte[] data1 = Common.HexStringToByteArray(cmd1);
                                        ShowMessageInWindow("发送指令： " + cmd1);
                                        Send(session.SockeClient, data1);
                                    }
                                }
                                else
                                {
                                    AsynConnect(session.IP, 502);
                                }
                            }
                            try
                            {
                                // 使用Task.Delay替代Delay方法，避免UI阻塞
                                Task.Delay(3000, cancellationTokenSource?.Token ?? CancellationToken.None).Wait();
                            }
                            catch (OperationCanceledException)
                            {
                                break; // 取消操作，退出循环
                            }
                        }

                    }
                }
                catch (Exception ex)
                {
                    ShowMessageInWindow("CollectData  采集出现异常" + ex.Message);
                }

            }

        }

        #region 窗体事件方法
        /// <summary>
        /// 双击图标事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void IcnSys_Click(object sender, EventArgs e)
        {
            try
            {
                Visible = true;//显示窗体
                ShowInTaskbar = true;//不在任务栏显示
                WindowState = FormWindowState.Normal;//窗体大小
            }
            catch (Exception ex)
            {
                Common.WriteErrorLog(MethodBase.GetCurrentMethod().Name + "\r\n" + ex.Message);//将出错信息写入错误日志
            }
        }
        /// <summary>
        /// 右键菜单退出事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void TsbtnExit_Click(object sender, EventArgs e)
        {
            try
            {
                Thread.Sleep(1000);
                CloseAllSocket(sessionPool);
                Close();//关闭窗体
                Dispose();//释放资源
                Application.Exit();//退出程序
            }
            catch (Exception ex)
            {
                Common.WriteErrorLog(MethodBase.GetCurrentMethod().Name + "\r\n" + ex.Message);//将出错信息写入错误日志
            }
        }
        /// <summary>
        /// 窗口大小改变事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void FrmMain_SizeChanged(object sender, EventArgs e)
        {
            try
            {
                //最小化时只显示图标
                if (WindowState == FormWindowState.Minimized)
                {
                    ShowInTaskbar = false;//不在任务栏显示
                    icnSys.Visible = true;//在任务栏通知区域显示图标
                }
            }
            catch (Exception ex)
            {
                Common.WriteErrorLog(MethodBase.GetCurrentMethod().Name + "\r\n" + ex.Message);//将出错信息写入错误日志
            }
        }
        /// <summary>
        /// 关闭窗体时默认为最小化
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void FrmMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            try
            {
                ShowMessageInWindow("正在关闭程序，请稍候...");
                
                // 设置关闭标志
                isShuttingDown = true;
                
                // 取消所有线程
                if (cancellationTokenSource != null)
                {
                    cancellationTokenSource.Cancel();
                }
                
                // 停止所有定时器
                if (timer1 != null) timer1.Stop();
                if (timer2 != null) timer2.Stop();
                if (timer3 != null) timer3.Stop();
                if (timer4 != null) timer4.Stop();
                if (monitorTimer != null) monitorTimer.Stop();
                if (messageUpdateTimer != null) messageUpdateTimer.Stop();
                
                // 释放性能优化组件
                if (cacheManager != null)
                {
                    try
                    {
                        cacheManager.ForceFlush(); // 强制刷新缓存
                        cacheManager.Dispose();
                    }
                    catch (Exception ex)
                    {
                        Common.WriteErrorLog($"缓存管理器释放异常: {ex.Message}");
                    }
                }
                
                if (taskManager != null)
                {
                    try
                    {
                        taskManager.CancelAllTasks();
                        taskManager.Dispose();
                    }
                    catch (Exception ex)
                    {
                        Common.WriteErrorLog($"任务管理器释放异常: {ex.Message}");
                    }
                }
                
                // 等待线程退出（最多等待5秒）
                int waitTime = 0;
                while ((tRead?.IsAlive == true || webSocktThread?.IsAlive == true || 
                       hylThread?.IsAlive == true || cylThread?.IsAlive == true || 
                       wsThread?.IsAlive == true) && waitTime < 50)
                {
                    Thread.Sleep(100);
                    waitTime++;
                    Application.DoEvents();
                }
                
                // 强制关闭WebSocket服务器
                if (wssv != null)
                {
                    try
                    {
                        wssv.Stop();
                    }
                    catch { }
                }
                
                // 关闭所有Socket连接
                foreach (var session in sessionPool.Values.ToList())
                {
                    try
                    {
                        SafeClose(session?.SockeClient);
                    }
                    catch { }
                }
                sessionPool.Clear();
                
                ShowMessageInWindow("程序已安全关闭");
            }
            catch (Exception ex)
            {
                Common.WriteErrorLog($"窗体关闭异常: {ex.Message}");
            }
        }

        /// <summary>
        /// 退出-关闭窗体
        /// 刘金鹏 2015-9-10
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void TsbtnClose_Click(object sender, EventArgs e)
        {
            try
            {
                Thread.Sleep(1000);
                CloseAllSocket(sessionPool);
                Close();//关闭窗体
                Dispose();//释放资源
                Application.Exit();//退出程序
            }
            catch (Exception ex)
            {
                Common.WriteErrorLog(MethodBase.GetCurrentMethod().Name + "\r\n" + ex.Message);//将出错信息写入错误日志
            }
        }

        #endregion


        #region 保存数据写入文本文件

        /// <summary>
        /// 将消息保存到文件中
        /// 刘金鹏 2015-9-29
        /// </summary>
        /// <param name="strMessage">消息内容</param>
        private void SaveMessage(string strMessage)
        {
            try
            {
                //没有消息内容时返回
                if (string.IsNullOrEmpty(strMessage))
                {
                    return;
                }
                //默认保存文件路径
                string filePath = Directory.GetCurrentDirectory() + "\\Message";
                if (!Directory.Exists(filePath))
                {
                    Directory.CreateDirectory(filePath);//创建目录
                }
                //取系统时间作为文件名
                string fileName = filePath + "\\Message" + DateTime.Now.Year.ToString() + "-" + DateTime.Now.Month.ToString() + "-" + DateTime.Now.Day.ToString() + ".txt";
                if (!File.Exists(fileName))
                {
                    File.CreateText(fileName).Close();//创建文本文件后关闭
                    //每天创建新文件时先清空窗体接收消息文本内容
                    Invoke(new Action(delegate
                    {
                        txtMessage.Text = "";
                    }));
                }
                //将消息内容写入文件中
                File.AppendAllText(fileName, strMessage + "\r\n");
            }
            catch (Exception ex)
            {
                Common.WriteErrorLog(MethodBase.GetCurrentMethod().Name + "\r\n" + ex.Message);//将出错信息写入错误日志
            }
        }

        #endregion

        #region 在消息区域显示数据
        public void ShowMessageInWindow(string message)
        {
            try
            {
                // 将消息添加到队列
                lock (messageQueueLock)
                {
                    messageQueue.Enqueue(message);
                }
            }
            catch (Exception ex)
            {
                // 如果队列操作失败，直接显示消息
                try
                {
                    if (txtMessage.InvokeRequired)
                    {
                        txtMessage.Invoke(new Action(() => AppendMessage(message)));
                    }
                    else
                    {
                        AppendMessage(message);
                    }
                }
                catch
                {
                    // 最后的备用方案：写入日志
                    Common.WriteErrorLog($"消息显示失败: {message}");
                }
            }
        }

        private void AppendMessage(string message)
        {
            txtMessage.AppendText("\r\n" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss =>") + message);

            // 超过1000行自动清空
            if (txtMessage.Lines.Length > 1000)
            {
                txtMessage.Clear();
                txtMessage.AppendText("【日志已自动清空，防止内存溢出】\r\n");
            }
        }

        public void ShowMessageInWindowTest(string message)
        {
            // txtMessage.Text += message + "\r\n";
            //  txtMessage.Text = "\r\n" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss =>") + message + txtMessage.Text;
            //  接收的消息写入窗体文本框，多线程委托方式写入
            Invoke(new Action(delegate
            {
                // txtMessage.Text = "\r\n" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss =>") + message + txtMessage.Text;
                txtMessage.AppendText("\r\n" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss =>") + message);
            }));
        }


        #endregion

        /// <summary>
        /// 计时器，等待指定时间
        /// </summary>
        /// <param name="milliSecond"></param>
        public static void Delay(int milliSecond)
        {
            int start = Environment.TickCount;
            while (Math.Abs(Environment.TickCount - start) < milliSecond)
            {
                Application.DoEvents();
            }
        }

        public string DEC_to_HEX(string s)
        {
            //     string value = val.ToString("X");  int类型转为string 16进制类型
            int val = int.Parse(s);
            string value = val.ToString("X");
            string result = "";
            if (value.Length == 1)

            {
                result = "00 0" + value.ToUpper();
            }
            else if (value.Length == 2)
            {
                result = "00 " + value.ToUpper();
            }
            else if (value.Length == 3)
            {
                result = "0" + value;
            }
            else
            {
                result = value;
            }
            return result;
        }

        public string DEC_to_HEX(int val)
        {
            string value = val.ToString("X");
            string result = "";
            if (value.Length == 1)

            {
                result = "00 0" + value.ToUpper();
            }
            else if (value.Length == 2)
            {
                result = "00 " + value.ToUpper();
            }
            else if (value.Length == 3)
            {
                result = "0" + value.Substring(0, 1) + " " + value.Substring(1, 2);
            }
            else
            {
                result = value;
            }
            return result;
        }

        //增加Crc16校验
        public string Full_Crc(string cmd)
        {
            Crc16 crc = new Crc16();
            string result = "";
            byte[] bytes = Common.HexStringToByteArray(cmd);
            byte[] crc16 = crc.crc16_bytes(bytes, bytes.Count());
            string s = Common.ByteArrayToHexString(crc16, 0, crc16.Count());
            result = cmd + s;
            result = result.ToUpper().Replace(" ", "");
            bytes = Common.HexStringToByteArray(result);
            result = Common.ByteArrayToHexString(bytes, 0, bytes.Count());
            return result;
        }

        /// <summary>  
        /// 字符串 ABCD 转为浮点数
        /// </summary>  
        /// <param name="s" />字符串  
        /// <returns>浮点数</returns>  
        private double StringToFloat(string s)
        {
            s = s.Replace(" ", "");
            Byte[] bytes = Common.HexStringToByteArray(s);
            bytes = bytes.Reverse().ToArray();  //反序
            float fNum = BitConverter.ToSingle(bytes, 0);
            return fNum;
        }

        /// <summary>  
        /// 字符串 CDAB 转为浮点数
        /// </summary>  
        /// <param name="s" />字符串  
        /// <returns>浮点数</returns>  
        private double StringToFloat2(string s)
        {
            s = s.Replace(" ", "");
            s = s.Substring(4, 4) + s.Substring(0, 4);
            Byte[] bytes = Common.HexStringToByteArray(s);
            bytes = bytes.Reverse().ToArray();  //反序
            float fNum = BitConverter.ToSingle(bytes, 0);
            return fNum;
        }

        // <summary>  
        /// 字符串转为双精度浮点数
        /// </summary>  
        /// <param name="s" />字符串
        /// <returns>返回双精度浮点数</returns>  
        private double StringToDouble(string s)
        {
            s = s.Replace(" ", "");
            Byte[] bytes = Common.HexStringToByteArray(s);
            bytes = bytes.Reverse().ToArray();  //反序
            double fNum = BitConverter.ToDouble(bytes, 0);
            return Math.Round(fNum, 2);
        }

        /// <summary>  
        /// 将BCD一字节数据转换到byte 十进制数据  
        /// </summary>  
        /// <param name="b" />字节数  
        /// <returns>返回转换后的BCD码</returns>  
        public string ConvertBCDToString(string s)
        {
            Byte b = Convert.ToByte(s, 2);
            //高四位  
            byte b1 = (byte)((b >> 4) & 0xF);
            //低四位  
            byte b2 = (byte)(b & 0xF);

            int i = (byte)(b1 * 10 + b2);
            return i.ToString();
        }


        /// <summary>  
        /// 将16进制字符串转为'，'逗号隔开的10进制字符串 
        /// </summary>  
        /// <param name="s" />16进制字符串  
        /// <returns>返回逗号隔开的10进制字符串</returns> 
        public string StringParse(string s, int p)
        {
            string result = "";
            int count = s.Length / 4;
            for (int i = 0; i < count; i++)
            {
                string ss = s.Substring(i * 4, 4);
                result += (double)Convert.ToInt32(ss, 16) / (double)p + ",";
            }
            result = result.Substring(0, result.Length - 1);
            return result;
        }


        /// <summary>  
        /// 保留多少位小数
        /// </summary>  
        /// <param name="p" />要转换的64位int数值 
        /// <param name="q" />保留几位小数
        /// <returns>返回double 类型结果</returns> 
        public double DecimalFormat(Int64 p, int q)
        {
            int j = 1;
            for (int i = 0; i < q; i++)
            {
                j = j * 10;
            }
            double result = (double)p / (double)j;
            result = Math.Round(result, q);
            return result;

        }

        /// <summary>  
        /// 将接收的数据写入基础数据表中
        /// </summary>
        private void AddRunData(ModelDevice mod, bool flag)
        {
            if (flag)
            {
                string sqlText = "";
                try
                {
                    sqlText = string.Format("insert into BASE_DATA_temp (TRAN_POINT_ID,TRAN_POINT_NAME,TEMPERATURE1,TEMPERATURE2,PRESSURE1,PRESSURE2,WATER_CONTENT1,WATER_CONTENT2,STIME) "
                                            + " values ('{0}','{1}','{2}','{3}','{4}','{5}','{6}','{7}',TO_DATE('{8}','yyyy-mm-dd hh24:mi:ss'))",
                                               mod.DeviceId, mod.DeviceName, mod.Temperature1, mod.Temperature2, mod.Pressure1, mod.Pressure2, mod.waterContent1, mod.waterContent2, DateTime.Now.ToString());

                    int intResult = Common.ExecuteNonQuery(sqlText);
                    if (intResult > 0)
                    {
                        ShowMessageInWindow("插入数据成功");
                    }

                }
                catch (Exception ex)
                {
                    ShowMessageInWindow("插入失败 " + ex.Message);
                    Common.WriteErrorLog(MethodBase.GetCurrentMethod().Name + "\r\n" + ex.Message + "\r\n" + sqlText);//将出错信息写入错误日志
                }
            }
        }

        /// <summary>  
        /// 将接收的数据写入基础数据表中
        /// </summary>
        private void AddWsWaterData(ModelDevice mod, bool flag)
        {
            if (flag)
            {
                string sqlText = "";
                try
                {
                    sqlText = string.Format("insert into DATA_WS_WATER_CONTENT (TRAN_POINT_ID,TRAN_POINT_NAME,WATER_CONTENT1,WATER_CONTENT2,STIME) "
                                            + " values ('{0}','{1}','{2}','{3}',TO_DATE('{4}','yyyy-mm-dd hh24:mi:ss'))",
                                               mod.DeviceId, mod.DeviceName, mod.waterContent1, mod.waterContent2, DateTime.Now.ToString());

                    int intResult = Common.ExecuteNonQuery(sqlText);
                    if (intResult > 0)
                    {
                        ShowMessageInWindow("插入数据成功");
                    }

                }
                catch (Exception ex)
                {
                    ShowMessageInWindow("插入失败 " + ex.Message);
                    Common.WriteErrorLog(MethodBase.GetCurrentMethod().Name + "\r\n" + ex.Message + "\r\n" + sqlText);//将出错信息写入错误日志
                }
            }
        }

        /// <summary>  
        /// 断点续传插入数据
        /// </summary>
        private void AddLostData(ModelDevice mod, bool flag)
        {
            if (flag)
            {
                string sqlText = "";
                try
                {
                    sqlText = string.Format("insert into DATA_HIS (TRAN_POINT_ID,TRAN_POINT_NAME,TEMPERATURE1,TEMPERATURE2,PRESSURE1,PRESSURE2,WATER_CONTENT1,WATER_CONTENT2,STIME,FLOWMETER1_VALUE,FLOWMETER2_VALUE,FLOW1_RATE,FLOW2_RATE,MARK) "
                                            + " values ('{0}','{1}','{2}','{3}','{4}','{5}','{6}','{7}',TO_DATE('{8}','yyyy-mm-dd hh24:mi:ss'),'{9}','{10}','{11}','{12}','{13}')",
                                               mod.DeviceId, mod.DeviceName, mod.Temperature1, mod.Temperature2, mod.Pressure1, mod.Pressure2, mod.waterContent1, mod.waterContent2, mod.BreakTime, mod.Flow1, mod.Flow2, mod.Flow1Rate, mod.Flow2Rate, "1");

                    int intResult = Common.ExecuteNonQuery(sqlText);
                    if (intResult > 0)
                    {
                        ShowMessageInWindow("断点续传 插入数据成功");
                    }

                    sqlText = string.Format("insert into DATA_HIS_temp (TRAN_POINT_ID,TRAN_POINT_NAME,TEMPERATURE1,TEMPERATURE2,PRESSURE1,PRESSURE2,WATER_CONTENT1,WATER_CONTENT2,STIME,FLOWMETER1_VALUE,FLOWMETER2_VALUE,FLOW1_RATE,FLOW2_RATE,MARK) "
                                           + " values ('{0}','{1}','{2}','{3}','{4}','{5}','{6}','{7}',TO_DATE('{8}','yyyy-mm-dd hh24:mi:ss'),'{9}','{10}','{11}','{12}','{13}')",
                                              mod.DeviceId, mod.DeviceName, mod.Temperature1, mod.Temperature2, mod.Pressure1, mod.Pressure2, mod.waterContent1, mod.waterContent2, mod.BreakTime, mod.Flow1, mod.Flow2, mod.Flow1Rate, mod.Flow2Rate, "1");

                    intResult = Common.ExecuteNonQuery(sqlText);
                    if (intResult > 0)
                    {
                        ShowMessageInWindow("断点续传 插入数据成功");
                    }

                }
                catch (Exception ex)
                {
                    ShowMessageInWindow("插入失败 " + ex.Message);
                    Common.WriteErrorLog(MethodBase.GetCurrentMethod().Name + "\r\n" + ex.Message + "\r\n" + sqlText);//将出错信息写入错误日志
                }
            }
        }

        /// <summary>  
        /// 写入楚一联Flow1数据表中
        /// </summary>
        private void AddCylFlow1Data(ModelDevice mod, bool flag)
        {
            if (flag)
            {
                string sqlText = "";
                try
                {

                    #region 仪表参数信息         
                    mod.DeviceId = mod.DeviceId == null ? "" : mod.DeviceId;                //设备编号ID
                    mod.DeviceName = mod.DeviceName == null ? "" : mod.DeviceName;          //设备名称                
                    #endregion

                    sqlText = string.Format("insert into data_cyl_flow1 (TRAN_POINT_ID,TRAN_POINT_NAME,FLOWMETER1_VALUE,STIME) "
                                            + " values ('{0}','{1}','{2}',TO_DATE('{3}','yyyy-mm-dd hh24:mi:ss'))",
                                               mod.DeviceId, mod.DeviceName, mod.Flow1, DateTime.Now.ToString());

                    int intResult = Common.ExecuteNonQuery(sqlText);
                    if (intResult > 0)
                    {
                        ShowMessageInWindow("插入楚一联流量计1 数据成功");
                    }

                }
                catch (Exception ex)
                {
                    ShowMessageInWindow("插入失败 " + ex.Message);
                    Common.WriteErrorLog(MethodBase.GetCurrentMethod().Name + "\r\n" + ex.Message + "\r\n" + sqlText);//将出错信息写入错误日志
                }
            }
        }

        /// <summary>  
        /// 写入楚一联Flow2数据表中
        /// </summary>
        private void AddCylFlow2Data(ModelDevice mod, bool flag)
        {
            if (flag)
            {
                string sqlText = "";
                try
                {

                    #region 仪表参数信息         
                    mod.DeviceId = mod.DeviceId == null ? "" : mod.DeviceId;                //设备编号ID
                    mod.DeviceName = mod.DeviceName == null ? "" : mod.DeviceName;          //设备名称                
                    #endregion

                    sqlText = string.Format("insert into data_cyl_flow2 (TRAN_POINT_ID,TRAN_POINT_NAME,FLOWMETER2_VALUE,FLOW2_RATE,STIME) "
                                            + " values ('{0}','{1}','{2}','{3}',TO_DATE('{4}','yyyy-mm-dd hh24:mi:ss'))",
                                               mod.DeviceId, mod.DeviceName, mod.Flow2, mod.Flow2Rate, DateTime.Now.ToString());

                    int intResult = Common.ExecuteNonQuery(sqlText);
                    if (intResult > 0)
                    {
                        ShowMessageInWindow("插入楚一联流量计2 数据成功");
                    }

                }
                catch (Exception ex)
                {
                    ShowMessageInWindow("插入失败 " + ex.Message);
                    Common.WriteErrorLog(MethodBase.GetCurrentMethod().Name + "\r\n" + ex.Message + "\r\n" + sqlText);//将出错信息写入错误日志
                }
            }
        }

        /// <summary>  
        /// 楚一联插入含水数据
        /// </summary>
        private void AddCylWaterContentData(ModelDevice mod, bool flag)
        {
            if (flag)
            {
                string sqlText = "";
                try
                {

                    #region 仪表参数信息         
                    mod.DeviceId = mod.DeviceId == null ? "" : mod.DeviceId;                //设备编号ID
                    mod.DeviceName = mod.DeviceName == null ? "" : mod.DeviceName;          //设备名称                
                    #endregion

                    sqlText = string.Format("insert into data_cyl_water_content (TRAN_POINT_ID,TRAN_POINT_NAME,water_content,STIME) "
                                            + " values ('{0}','{1}','{2}',TO_DATE('{3}','yyyy-mm-dd hh24:mi:ss'))",
                                               mod.DeviceId, mod.DeviceName, mod.waterContent1, DateTime.Now.ToString());

                    int intResult = Common.ExecuteNonQuery(sqlText);
                    if (intResult > 0)
                    {
                        ShowMessageInWindow("插入楚一联流量计2 数据成功");
                    }

                }
                catch (Exception ex)
                {
                    ShowMessageInWindow("插入失败 " + ex.Message);
                    Common.WriteErrorLog(MethodBase.GetCurrentMethod().Name + "\r\n" + ex.Message + "\r\n" + sqlText);//将出错信息写入错误日志
                }
            }
        }

        /// <summary>  
        /// 将接收的数据写入流量计表数据表中
        /// </summary>
        private void AddFlowRunData(ModelDevice mod, bool flag)
        {
            if (flag)
            {
                string sqlText = "";
                try
                {

                    #region 仪表参数信息         
                    mod.DeviceId = mod.DeviceId == null ? "" : mod.DeviceId;                //设备编号ID
                    mod.DeviceName = mod.DeviceName == null ? "" : mod.DeviceName;          //设备名称                
                    #endregion

                    sqlText = string.Format("insert into FLOW_BASE_DATA (TRAN_POINT_ID,TRAN_POINT_NAME,FLOWMETER1_VALUE,FLOWMETER2_VALUE,STIME,flow1_rate,flow2_rate) "
                                            + " values ('{0}','{1}','{2}','{3}',TO_DATE('{4}','yyyy-mm-dd hh24:mi:ss'),'{5}','{6}')",
                                               mod.DeviceId, mod.DeviceName, mod.Flow1, mod.Flow2, DateTime.Now.ToString(), mod.Flow1Rate, mod.Flow2Rate);

                    int intResult = Common.ExecuteNonQuery(sqlText);
                    if (intResult > 0)
                    {
                        ShowMessageInWindow("插入数据成功");
                    }

                }
                catch (Exception ex)
                {
                    ShowMessageInWindow("插入失败 " + ex.Message);
                    Common.WriteErrorLog(MethodBase.GetCurrentMethod().Name + "\r\n" + ex.Message + "\r\n" + sqlText);//将出错信息写入错误日志
                }
            }
        }

        public void CollectCy1Flow1()
        {
            try
            {
                string url = "http://192.168.60.150:39320/iotgateway/read?ids=饶阳工区大站.楚一联油区.DB301.D14";
                string reult = httpGet(url);
                JObject json = (JObject)JsonConvert.DeserializeObject(reult);
                string value = json["readResults"][0]["v"].ToString();
                if (value != null && value != "")
                {
                    ModelDevice mod = new ModelDevice();
                    string id = "4";
                    string name = "楚一联";

                    mod.DeviceId = id;
                    mod.DeviceName = name;
                    mod.Flow1 = double.Parse(value);
                    AddCylFlow1Data(mod, true);
                }

            }
            catch (Exception ex)
            {
                ShowMessageInWindow(MethodBase.GetCurrentMethod().Name + "\r\n" + ex.Message);
                Common.WriteErrorLog(MethodBase.GetCurrentMethod().Name + "\r\n" + ex.Message);//将出错信息写入错误日志           
            }
        }

        private string dateTime(int second)
        {
            return new DateTime(1970, 01, 01, 00, 00, 00).AddSeconds(second).ToString("yyyy-MM-dd HH:mm:ss");
        }

        public int StringToDec(string s)
        {
            int n = 0;
            for (int i = 0; i < s.Length; i++)
            {
                n = 10 * n + (s[i] - '0');
            }
            return n;

        }

        /// <summary>
        /// 得到流量计底数读数，用两个寄存器地址表示
        /// </summary>
        /// <param name="value">返回高位和低位的值</param>
        /// <returns></returns>
        public flowBaseDataModel getFlowBase(string value)
        {
            int val = int.Parse(value);
            string strA = val.ToString("x8");
            string hStr = strA.Substring(0, 4);
            string lStr = strA.Substring(4);
            flowBaseDataModel mod = new flowBaseDataModel();
            mod.high = Convert.ToInt32(hStr, 16);
            mod.low = Convert.ToInt32(lStr, 16);
            return mod;
        }

        /// <summary>
        /// 流量计底数的高位和低位
        /// </summary>
        public class flowBaseDataModel
        {
            public int high { get; set; }
            public int low { get; set; }
        }

        [DllImportAttribute("kernel32.dll", EntryPoint = "SetProcessWorkingSetSize", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)]
        private static extern int SetProcessWorkingSetSize(IntPtr process, int minimumWorkingSetSize, int maximumWorkingSetSize);
        /// <summary>
        /// 清理内存
        /// </summary>
        private void ClearMemory()
        {
            GC.Collect();
            GC.WaitForPendingFinalizers();
            SetProcessWorkingSetSize(System.Diagnostics.Process.GetCurrentProcess().Handle, -1, -1);
        }

        /// <summary>
        /// 指定Url地址使用Get 方式获取全部字符串
        /// </summary>
        /// <param name="url">请求链接地址</param>
        /// <returns></returns>
        public static string httpGet(string url)
        {
            string result = "";
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
            HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
            Stream stream = resp.GetResponseStream();
            try
            {
                //获取内容
                using (StreamReader reader = new StreamReader(stream))
                {
                    result = reader.ReadToEnd();
                }
            }
            finally
            {
                stream.Close();
            }
            return result;
        }

        /// <summary>
        /// 此类是为了实现websocket 1分钟上传一次功能所建立
        /// </summary>
        public class TimeModel
        {
            /// <summary>
            /// 一般数据的采集时间
            /// </summary>
            public DateTime commonTime { get; set; }
            /// <summary>
            /// 流量计采集时间
            /// </summary>
            public DateTime flowTime { get; set; }
        }

        // 线程和Timer全局变量
        private Thread tRead, webSocktThread, hylThread, cylThread, wsThread;
        
        // 消息队列和UI更新定时器
        private readonly Queue<string> messageQueue = new Queue<string>();
        private readonly object messageQueueLock = new object();
        private System.Windows.Forms.Timer messageUpdateTimer;

        // 消息更新定时器事件处理
        private void MessageUpdateTimer_Tick(object sender, EventArgs e)
        {
            try
            {
                List<string> messagesToProcess = new List<string>();
                
                // 从队列中取出所有待处理的消息
                lock (messageQueueLock)
                {
                    while (messageQueue.Count > 0)
                    {
                        messagesToProcess.Add(messageQueue.Dequeue());
                    }
                }
                
                // 批量处理消息
                if (messagesToProcess.Count > 0)
                {
                    if (txtMessage.InvokeRequired)
                    {
                        txtMessage.Invoke(new Action(() => ProcessBatchMessages(messagesToProcess)));
                    }
                    else
                    {
                        ProcessBatchMessages(messagesToProcess);
                    }
                }
            }
            catch (Exception ex)
            {
                Common.WriteErrorLog($"消息更新定时器异常: {ex.Message}");
            }
        }
        
        // 批量处理消息
        private void ProcessBatchMessages(List<string> messages)
        {
            try
            {
                foreach (string message in messages)
                {
                    AppendMessage(message);
                }
            }
            catch (Exception ex)
            {
                Common.WriteErrorLog($"批量消息处理异常: {ex.Message}");
            }
        }

        // 统一自愈线程启动方法
        private Thread StartThreadWithSelfHeal(ThreadStart action, string threadName)
        {
            Thread t = new Thread(() =>
            {
                while (!cancellationTokenSource?.Token.IsCancellationRequested == true && !isShuttingDown)
                {
                    try
                    {
                        action();
                    }
                    catch (Exception ex)
                    {
                        ShowMessageInWindow($"{threadName} 线程异常: {ex.Message}");
                        try
                        {
                            // 使用Task.Delay替代Thread.Sleep，支持取消操作
                            Task.Delay(5000, cancellationTokenSource?.Token ?? CancellationToken.None).Wait();
                        }
                        catch (OperationCanceledException)
                        {
                            break; // 取消操作，退出循环
                        }
                    }
                }
            });
            t.IsBackground = true;
            t.Start();
            return t;
        }

        // 启动所有采集线程
        public void StartAllThreads()
        {
            tRead = StartThreadWithSelfHeal(CollectData, "CollectData");
            webSocktThread = StartThreadWithSelfHeal(InitWebSockt, "WebSocket");
            hylThread = StartThreadWithSelfHeal(hylCollect, "hylCollect");
            cylThread = StartThreadWithSelfHeal(cylCollect, "cylCollect");
        //    wsThread = StartThreadWithSelfHeal(wsWaterCollect, "wsWaterCollect");
        }

        // 健康监控Timer
        private void StartMonitor()
        {
            monitorTimer = new System.Windows.Forms.Timer();
            monitorTimer.Interval = 60 * 1000;
            monitorTimer.Tick += (s, e) =>
            {
                // 检查线程
                if (tRead == null || !tRead.IsAlive)
                {
                    tRead = StartThreadWithSelfHeal(CollectData, "CollectData");
                    ShowMessageInWindow("自动重启CollectData线程");
                }
                if (webSocktThread == null || !webSocktThread.IsAlive)
                {
                    webSocktThread = StartThreadWithSelfHeal(InitWebSockt, "WebSocket");
                    ShowMessageInWindow("自动重启WebSocket线程");
                }
                if (hylThread == null || !hylThread.IsAlive)
                {
                    hylThread = StartThreadWithSelfHeal(hylCollect, "hylCollect");
                    ShowMessageInWindow("自动重启hylCollect线程");
                }
                if (cylThread == null || !cylThread.IsAlive)
                {
                    cylThread = StartThreadWithSelfHeal(cylCollect, "cylCollect");
                    ShowMessageInWindow("自动重启cylCollect线程");
                }
                if (wsThread == null || !wsThread.IsAlive)
                {
                    wsThread = StartThreadWithSelfHeal(wsWaterCollect, "wsWaterCollect");
                    ShowMessageInWindow("自动重启wsWaterCollect线程");
                }
                // 检查Socket
                foreach (var session in sessionPool.Values.ToList())
                {
                    if (session == null || session.SockeClient == null || !IsSocketConnected(session.SockeClient))
                    {
                        ShowMessageInWindow($"监控发现Socket失效，自动重连: {session?.IP}");
                        SafeClose(session?.SockeClient);
                        if (session != null) sessionPool.Remove(session.IP);
                        AsynConnect(session?.IP, 502);
                    }
                }
            };
            monitorTimer.Start();
        }

        // Socket连接检测
        private bool IsSocketConnected(Socket s)
        {
            try
            {
                return !(s.Poll(1, SelectMode.SelectRead) && s.Available == 0);
            }
            catch { return false; }
        }
    }
}
